react-native-inapp-inspector 2.5.1 → 2.5.3

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 (308) hide show
  1. package/README.ar.md +151 -53
  2. package/README.de.md +150 -52
  3. package/README.es.md +139 -42
  4. package/README.fr.md +151 -53
  5. package/README.hi.md +141 -43
  6. package/README.ja.md +150 -69
  7. package/README.ko.md +153 -55
  8. package/README.md +73 -14
  9. package/README.pt-BR.md +152 -54
  10. package/README.ru.md +153 -55
  11. package/README.zh-CN.md +95 -219
  12. package/android/.gradle/9.2.0/fileHashes/fileHashes.lock +0 -0
  13. package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
  14. package/android/.gradle/buildOutputCleanup/cache.properties +1 -1
  15. package/android/build/.transforms/ad628164ecef2a7cc593f0fd2f4050ce/results.bin +1 -0
  16. package/android/build/.transforms/ad628164ecef2a7cc593f0fd2f4050ce/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/inappinspector/BuildConfig.dex +0 -0
  17. package/android/build/.transforms/ad628164ecef2a7cc593f0fd2f4050ce/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/inappinspector/InAppInspectorFloatingView$iconView$1.dex +0 -0
  18. package/android/build/.transforms/ad628164ecef2a7cc593f0fd2f4050ce/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/inappinspector/InAppInspectorFloatingView.dex +0 -0
  19. package/android/build/.transforms/ad628164ecef2a7cc593f0fd2f4050ce/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/inappinspector/NativeNetworkInspectorSpec.dex +0 -0
  20. package/android/build/.transforms/ad628164ecef2a7cc593f0fd2f4050ce/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/inappinspector/NetworkInspectorModule$Companion.dex +0 -0
  21. package/android/build/.transforms/ad628164ecef2a7cc593f0fd2f4050ce/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/inappinspector/NetworkInspectorModule$activityEventListener$1.dex +0 -0
  22. package/android/build/.transforms/ad628164ecef2a7cc593f0fd2f4050ce/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/inappinspector/NetworkInspectorModule$frameCallback$1.dex +0 -0
  23. package/android/build/.transforms/ad628164ecef2a7cc593f0fd2f4050ce/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/inappinspector/NetworkInspectorModule$getCapturedMedia$lambda$57$$inlined$sortedByDescending$1.dex +0 -0
  24. package/android/build/.transforms/ad628164ecef2a7cc593f0fd2f4050ce/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/inappinspector/NetworkInspectorModule$shakeListener$1.dex +0 -0
  25. package/android/build/.transforms/ad628164ecef2a7cc593f0fd2f4050ce/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/inappinspector/NetworkInspectorModule$startVideoRecording$2$1.dex +0 -0
  26. package/android/build/.transforms/ad628164ecef2a7cc593f0fd2f4050ce/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/inappinspector/NetworkInspectorModule.dex +0 -0
  27. package/android/build/.transforms/ad628164ecef2a7cc593f0fd2f4050ce/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/inappinspector/NetworkInspectorPackage.dex +0 -0
  28. package/android/build/.transforms/ad628164ecef2a7cc593f0fd2f4050ce/transformed/bundleLibRuntimeToDirDebug/desugar_graph.bin +0 -0
  29. package/android/build/.transforms/c93e459e24d856bde563ebb048265732/results.bin +1 -0
  30. package/android/build/.transforms/c93e459e24d856bde563ebb048265732/transformed/classes/classes_dex/classes.dex +0 -0
  31. package/android/build/generated/source/buildConfig/debug/com/inappinspector/BuildConfig.java +10 -0
  32. package/android/build/generated/source/codegen/java/com/inappinspector/NativeNetworkInspectorSpec.java +160 -0
  33. package/android/build/generated/source/codegen/jni/CMakeLists.txt +28 -0
  34. package/android/build/generated/source/codegen/jni/RNInAppInspectorSpec-generated.cpp +212 -0
  35. package/android/build/generated/source/codegen/jni/RNInAppInspectorSpec.h +31 -0
  36. package/android/build/generated/source/codegen/jni/react/renderer/components/RNInAppInspectorSpec/ComponentDescriptors.cpp +22 -0
  37. package/android/build/generated/source/codegen/jni/react/renderer/components/RNInAppInspectorSpec/ComponentDescriptors.h +24 -0
  38. package/android/build/generated/source/codegen/jni/react/renderer/components/RNInAppInspectorSpec/EventEmitters.cpp +16 -0
  39. package/android/build/generated/source/codegen/jni/react/renderer/components/RNInAppInspectorSpec/EventEmitters.h +17 -0
  40. package/android/build/generated/source/codegen/jni/react/renderer/components/RNInAppInspectorSpec/Props.cpp +19 -0
  41. package/android/build/generated/source/codegen/jni/react/renderer/components/RNInAppInspectorSpec/Props.h +18 -0
  42. package/android/build/generated/source/codegen/jni/react/renderer/components/RNInAppInspectorSpec/RNInAppInspectorSpecJSI.h +300 -0
  43. package/android/build/generated/source/codegen/jni/react/renderer/components/RNInAppInspectorSpec/ShadowNodes.cpp +17 -0
  44. package/android/build/generated/source/codegen/jni/react/renderer/components/RNInAppInspectorSpec/ShadowNodes.h +23 -0
  45. package/android/build/generated/source/codegen/jni/react/renderer/components/RNInAppInspectorSpec/States.cpp +16 -0
  46. package/android/build/generated/source/codegen/jni/react/renderer/components/RNInAppInspectorSpec/States.h +20 -0
  47. package/android/build/generated/source/codegen/schema.json +1 -0
  48. package/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/AndroidManifest.xml +7 -0
  49. package/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/output-metadata.json +18 -0
  50. package/android/build/intermediates/aar_metadata/debug/writeDebugAarMetadata/aar-metadata.properties +6 -0
  51. package/android/build/intermediates/annotation_processor_list/debug/javaPreCompileDebug/annotationProcessors.json +1 -0
  52. package/android/build/intermediates/compile_library_classes_jar/debug/bundleLibCompileToJarDebug/classes.jar +0 -0
  53. package/android/build/intermediates/compile_r_class_jar/debug/generateDebugRFile/R.jar +0 -0
  54. package/android/build/intermediates/compile_symbol_list/debug/generateDebugRFile/R.txt +0 -0
  55. package/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties +1 -0
  56. package/android/build/intermediates/incremental/debug/packageDebugResources/merger.xml +2 -0
  57. package/android/build/intermediates/incremental/mergeDebugJniLibFolders/merger.xml +2 -0
  58. package/android/build/intermediates/incremental/mergeDebugShaders/merger.xml +2 -0
  59. package/android/build/intermediates/incremental/packageDebugAssets/merger.xml +2 -0
  60. package/android/build/intermediates/java_res/debug/processDebugJavaRes/out/META-INF/react-native-inapp-inspector_debug.kotlin_module +0 -0
  61. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/inappinspector/BuildConfig.class +0 -0
  62. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/inappinspector/NativeNetworkInspectorSpec.class +0 -0
  63. package/android/build/intermediates/local_only_symbol_list/debug/parseDebugLocalResources/R-def.txt +2 -0
  64. package/android/build/intermediates/manifest_merge_blame_file/debug/processDebugManifest/manifest-merger-blame-debug-report.txt +7 -0
  65. package/android/build/intermediates/merged_manifest/debug/processDebugManifest/AndroidManifest.xml +7 -0
  66. package/android/build/intermediates/navigation_json/debug/extractDeepLinksDebug/navigation.json +1 -0
  67. package/android/build/intermediates/nested_resources_validation_report/debug/generateDebugResources/nestedResourcesValidationReport.txt +1 -0
  68. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/META-INF/react-native-inapp-inspector_debug.kotlin_module +0 -0
  69. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/inappinspector/BuildConfig.class +0 -0
  70. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/inappinspector/InAppInspectorFloatingView$iconView$1.class +0 -0
  71. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/inappinspector/InAppInspectorFloatingView.class +0 -0
  72. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/inappinspector/NativeNetworkInspectorSpec.class +0 -0
  73. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/inappinspector/NetworkInspectorModule$Companion.class +0 -0
  74. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/inappinspector/NetworkInspectorModule$activityEventListener$1.class +0 -0
  75. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/inappinspector/NetworkInspectorModule$frameCallback$1.class +0 -0
  76. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/inappinspector/NetworkInspectorModule$getCapturedMedia$lambda$57$$inlined$sortedByDescending$1.class +0 -0
  77. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/inappinspector/NetworkInspectorModule$shakeListener$1.class +0 -0
  78. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/inappinspector/NetworkInspectorModule$startVideoRecording$2$1.class +0 -0
  79. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/inappinspector/NetworkInspectorModule.class +0 -0
  80. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/inappinspector/NetworkInspectorPackage.class +0 -0
  81. package/android/build/intermediates/runtime_library_classes_jar/debug/bundleLibRuntimeToJarDebug/classes.jar +0 -0
  82. package/android/build/intermediates/symbol_list_with_package_name/debug/generateDebugRFile/package-aware-r.txt +1 -0
  83. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab +0 -0
  84. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream +0 -0
  85. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream.len +0 -0
  86. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.len +0 -0
  87. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.values.at +0 -0
  88. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab_i +0 -0
  89. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab_i.len +0 -0
  90. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab +0 -0
  91. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream +0 -0
  92. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream.len +0 -0
  93. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.len +0 -0
  94. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.values.at +0 -0
  95. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab_i +0 -0
  96. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab_i.len +0 -0
  97. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab +0 -0
  98. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream +0 -0
  99. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream.len +0 -0
  100. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.len +0 -0
  101. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.values.at +0 -0
  102. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i +0 -0
  103. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i.len +0 -0
  104. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab +0 -0
  105. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab.keystream +0 -0
  106. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab.keystream.len +0 -0
  107. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab.len +0 -0
  108. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab.values.at +0 -0
  109. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab_i +0 -0
  110. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab_i.len +0 -0
  111. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab +0 -0
  112. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream +0 -0
  113. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream.len +0 -0
  114. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.len +0 -0
  115. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.values.at +0 -0
  116. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i +0 -0
  117. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i.len +0 -0
  118. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab +0 -0
  119. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream +0 -0
  120. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream.len +0 -0
  121. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.len +0 -0
  122. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values.at +0 -0
  123. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab_i +0 -0
  124. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab_i.len +0 -0
  125. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab +0 -0
  126. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream +0 -0
  127. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream.len +0 -0
  128. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.len +0 -0
  129. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.values.at +0 -0
  130. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab_i +0 -0
  131. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab_i.len +0 -0
  132. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab +0 -0
  133. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.keystream +0 -0
  134. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.keystream.len +0 -0
  135. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.len +0 -0
  136. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.values.at +0 -0
  137. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab_i +0 -0
  138. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab_i.len +0 -0
  139. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab +0 -0
  140. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream +0 -0
  141. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream.len +0 -0
  142. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.len +0 -0
  143. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.values.at +0 -0
  144. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab_i +0 -0
  145. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab_i.len +0 -0
  146. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/counters.tab +2 -0
  147. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab +0 -0
  148. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.keystream +0 -0
  149. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.keystream.len +0 -0
  150. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.len +0 -0
  151. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.values.at +0 -0
  152. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab_i +0 -0
  153. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab_i.len +0 -0
  154. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab +0 -0
  155. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream +0 -0
  156. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream.len +0 -0
  157. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.len +0 -0
  158. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.values.at +0 -0
  159. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i +0 -0
  160. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i.len +0 -0
  161. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab +0 -0
  162. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream +0 -0
  163. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream.len +0 -0
  164. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.len +0 -0
  165. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.values.at +0 -0
  166. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab_i +0 -0
  167. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab_i.len +0 -0
  168. package/android/build/kotlin/compileDebugKotlin/cacheable/last-build.bin +0 -0
  169. package/android/build/kotlin/compileDebugKotlin/classpath-snapshot/shrunk-classpath-snapshot.bin +0 -0
  170. package/android/build/kotlin/compileDebugKotlin/local-state/build-history.bin +0 -0
  171. package/android/build/outputs/logs/manifest-merger-debug-report.txt +17 -0
  172. package/android/build/reports/problems/problems-report.html +659 -0
  173. package/android/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin +0 -0
  174. package/android/build/tmp/kotlin-classes/debug/META-INF/react-native-inapp-inspector_debug.kotlin_module +0 -0
  175. package/android/build/tmp/kotlin-classes/debug/com/inappinspector/InAppInspectorFloatingView$iconView$1.class +0 -0
  176. package/android/build/tmp/kotlin-classes/debug/com/inappinspector/InAppInspectorFloatingView.class +0 -0
  177. package/android/build/tmp/kotlin-classes/debug/com/inappinspector/NetworkInspectorModule$Companion.class +0 -0
  178. package/android/build/tmp/kotlin-classes/debug/com/inappinspector/NetworkInspectorModule$activityEventListener$1.class +0 -0
  179. package/android/build/tmp/kotlin-classes/debug/com/inappinspector/NetworkInspectorModule$frameCallback$1.class +0 -0
  180. package/android/build/tmp/kotlin-classes/debug/com/inappinspector/NetworkInspectorModule$getCapturedMedia$lambda$57$$inlined$sortedByDescending$1.class +0 -0
  181. package/android/build/tmp/kotlin-classes/debug/com/inappinspector/NetworkInspectorModule$shakeListener$1.class +0 -0
  182. package/android/build/tmp/kotlin-classes/debug/com/inappinspector/NetworkInspectorModule$startVideoRecording$2$1.class +0 -0
  183. package/android/build/tmp/kotlin-classes/debug/com/inappinspector/NetworkInspectorModule.class +0 -0
  184. package/android/build/tmp/kotlin-classes/debug/com/inappinspector/NetworkInspectorPackage.class +0 -0
  185. package/android/src/main/java/com/inappinspector/NetworkInspectorModule.kt +154 -9
  186. package/dist/commonjs/capture.d.ts +5 -2
  187. package/dist/commonjs/capture.js +1 -1
  188. package/dist/commonjs/components/CountryFlag.d.ts +10 -0
  189. package/dist/commonjs/components/CountryFlag.js +140 -0
  190. package/dist/commonjs/components/EmptyState.js +6 -6
  191. package/dist/commonjs/components/Inspector/DeviceInfoTab.js +36 -36
  192. package/dist/commonjs/components/Inspector/FabLauncher.js +12 -12
  193. package/dist/commonjs/components/Inspector/FloatingCaptureWidget.js +23 -23
  194. package/dist/commonjs/components/Inspector/GlobalCrashScreenModal.js +24 -24
  195. package/dist/commonjs/components/Inspector/InspectorHeader.js +40 -42
  196. package/dist/commonjs/components/Inspector/LanguageSelectorModal.js +23 -18
  197. package/dist/commonjs/components/Inspector/MainScreen.js +17 -17
  198. package/dist/commonjs/components/Inspector/MediaGalleryTab.js +52 -34
  199. package/dist/commonjs/components/Inspector/MediaPreviewModal.d.ts +20 -18
  200. package/dist/commonjs/components/Inspector/MediaPreviewModal.js +742 -304
  201. package/dist/commonjs/components/Inspector/NetworkFilterModal.js +21 -21
  202. package/dist/commonjs/components/Inspector/SecondaryTelemetryStrip.js +6 -6
  203. package/dist/commonjs/components/Inspector/SocketFilterModal.js +12 -12
  204. package/dist/commonjs/components/Inspector/TabBar.js +3 -3
  205. package/dist/commonjs/components/Inspector/UpdateAvailableModal.js +2 -2
  206. package/dist/commonjs/components/MetaAccordion.js +17 -17
  207. package/dist/commonjs/components/ModuleErrorBoundary.js +4 -4
  208. package/dist/commonjs/components/NetworkIcons.d.ts +19 -0
  209. package/dist/commonjs/components/NetworkIcons.js +87 -3
  210. package/dist/commonjs/components/SourcePageCard.js +9 -9
  211. package/dist/commonjs/constants/version.d.ts +1 -1
  212. package/dist/commonjs/constants/version.js +1 -1
  213. package/dist/commonjs/i18n/locales/ar.json +1 -1
  214. package/dist/commonjs/i18n/locales/bn.json +1 -1
  215. package/dist/commonjs/i18n/locales/de.json +1 -1
  216. package/dist/commonjs/i18n/locales/en.json +1 -1
  217. package/dist/commonjs/i18n/locales/es.json +1 -1
  218. package/dist/commonjs/i18n/locales/fr.json +1 -1
  219. package/dist/commonjs/i18n/locales/gu.json +1 -1
  220. package/dist/commonjs/i18n/locales/hi.json +1 -1
  221. package/dist/commonjs/i18n/locales/id.json +1 -1
  222. package/dist/commonjs/i18n/locales/it.json +1 -1
  223. package/dist/commonjs/i18n/locales/ja.json +1 -1
  224. package/dist/commonjs/i18n/locales/kn.json +1 -1
  225. package/dist/commonjs/i18n/locales/ko.json +1 -1
  226. package/dist/commonjs/i18n/locales/ml.json +1 -1
  227. package/dist/commonjs/i18n/locales/mr.json +1 -1
  228. package/dist/commonjs/i18n/locales/nl.json +1 -1
  229. package/dist/commonjs/i18n/locales/pa.json +1 -1
  230. package/dist/commonjs/i18n/locales/pl.json +1 -1
  231. package/dist/commonjs/i18n/locales/pt.json +1 -1
  232. package/dist/commonjs/i18n/locales/ru.json +1 -1
  233. package/dist/commonjs/i18n/locales/ta.json +1 -1
  234. package/dist/commonjs/i18n/locales/te.json +1 -1
  235. package/dist/commonjs/i18n/locales/tr.json +1 -1
  236. package/dist/commonjs/i18n/locales/vi.json +1 -1
  237. package/dist/commonjs/i18n/locales/zh.json +1 -1
  238. package/dist/commonjs/index.js +1 -1
  239. package/dist/commonjs/native/NativeInspector.d.ts +4 -0
  240. package/dist/commonjs/native/NativeInspector.js +1 -1
  241. package/dist/commonjs/native/NativeNetworkInspector.d.ts +1 -0
  242. package/dist/commonjs/styles/AppColors.d.ts +76 -0
  243. package/dist/commonjs/styles/AppColors.js +1 -1
  244. package/dist/commonjs/types/interfaces.d.ts +2 -0
  245. package/dist/esm/capture.d.ts +5 -2
  246. package/dist/esm/capture.js +1 -1
  247. package/dist/esm/components/CountryFlag.d.ts +10 -0
  248. package/dist/esm/components/CountryFlag.js +140 -0
  249. package/dist/esm/components/EmptyState.js +13 -13
  250. package/dist/esm/components/Inspector/DeviceInfoTab.js +176 -176
  251. package/dist/esm/components/Inspector/FabLauncher.js +37 -37
  252. package/dist/esm/components/Inspector/FloatingCaptureWidget.js +27 -27
  253. package/dist/esm/components/Inspector/GlobalCrashScreenModal.js +9 -9
  254. package/dist/esm/components/Inspector/InspectorHeader.js +43 -45
  255. package/dist/esm/components/Inspector/LanguageSelectorModal.js +107 -102
  256. package/dist/esm/components/Inspector/MainScreen.js +52 -52
  257. package/dist/esm/components/Inspector/MediaGalleryTab.js +100 -82
  258. package/dist/esm/components/Inspector/MediaPreviewModal.d.ts +20 -18
  259. package/dist/esm/components/Inspector/MediaPreviewModal.js +764 -326
  260. package/dist/esm/components/Inspector/NetworkFilterModal.js +37 -37
  261. package/dist/esm/components/Inspector/SecondaryTelemetryStrip.js +20 -20
  262. package/dist/esm/components/Inspector/SocketFilterModal.js +32 -32
  263. package/dist/esm/components/Inspector/TabBar.js +12 -12
  264. package/dist/esm/components/Inspector/UpdateAvailableModal.js +11 -11
  265. package/dist/esm/components/MetaAccordion.js +24 -24
  266. package/dist/esm/components/ModuleErrorBoundary.js +20 -20
  267. package/dist/esm/components/NetworkIcons.d.ts +19 -0
  268. package/dist/esm/components/NetworkIcons.js +89 -5
  269. package/dist/esm/components/SourcePageCard.js +21 -21
  270. package/dist/esm/constants/version.d.ts +1 -1
  271. package/dist/esm/constants/version.js +1 -1
  272. package/dist/esm/i18n/locales/ar.json +1 -1
  273. package/dist/esm/i18n/locales/bn.json +1 -1
  274. package/dist/esm/i18n/locales/de.json +1 -1
  275. package/dist/esm/i18n/locales/en.json +1 -1
  276. package/dist/esm/i18n/locales/es.json +1 -1
  277. package/dist/esm/i18n/locales/fr.json +1 -1
  278. package/dist/esm/i18n/locales/gu.json +1 -1
  279. package/dist/esm/i18n/locales/hi.json +1 -1
  280. package/dist/esm/i18n/locales/id.json +1 -1
  281. package/dist/esm/i18n/locales/it.json +1 -1
  282. package/dist/esm/i18n/locales/ja.json +1 -1
  283. package/dist/esm/i18n/locales/kn.json +1 -1
  284. package/dist/esm/i18n/locales/ko.json +1 -1
  285. package/dist/esm/i18n/locales/ml.json +1 -1
  286. package/dist/esm/i18n/locales/mr.json +1 -1
  287. package/dist/esm/i18n/locales/nl.json +1 -1
  288. package/dist/esm/i18n/locales/pa.json +1 -1
  289. package/dist/esm/i18n/locales/pl.json +1 -1
  290. package/dist/esm/i18n/locales/pt.json +1 -1
  291. package/dist/esm/i18n/locales/ru.json +1 -1
  292. package/dist/esm/i18n/locales/ta.json +1 -1
  293. package/dist/esm/i18n/locales/te.json +1 -1
  294. package/dist/esm/i18n/locales/tr.json +1 -1
  295. package/dist/esm/i18n/locales/vi.json +1 -1
  296. package/dist/esm/i18n/locales/zh.json +1 -1
  297. package/dist/esm/index.js +3 -3
  298. package/dist/esm/native/NativeInspector.d.ts +4 -0
  299. package/dist/esm/native/NativeInspector.js +1 -1
  300. package/dist/esm/native/NativeNetworkInspector.d.ts +1 -0
  301. package/dist/esm/styles/AppColors.d.ts +76 -0
  302. package/dist/esm/styles/AppColors.js +1 -1
  303. package/dist/esm/types/interfaces.d.ts +2 -0
  304. package/ios/NetworkInspectorModule.mm +487 -224
  305. package/package.json +1 -1
  306. package/react-native-inapp-inspector.podspec +1 -1
  307. package/src/native/NativeInspector.ts +22 -0
  308. package/src/native/NativeNetworkInspector.ts +1 -1
@@ -2,6 +2,7 @@
2
2
  #import <execinfo.h>
3
3
  #import <signal.h>
4
4
  #import <objc/runtime.h>
5
+ #import <objc/message.h>
5
6
  #import <unistd.h>
6
7
  #import <ReplayKit/ReplayKit.h>
7
8
  #import <AVFoundation/AVFoundation.h>
@@ -481,6 +482,144 @@ static void NativeExceptionHandler(NSException *exception) {
481
482
 
482
483
  @end
483
484
 
485
+ // ─────────────────────────────────────────────────────────────────────────────
486
+ // NATIVE CAMERA ROLL / PHOTO & VIDEO PICKER DELEGATE
487
+ // ─────────────────────────────────────────────────────────────────────────────
488
+
489
+ @interface InAppInspectorPickerDelegate : NSObject <UIImagePickerControllerDelegate, UINavigationControllerDelegate>
490
+ @property (nonatomic, copy) RCTPromiseResolveBlock resolve;
491
+ @property (nonatomic, copy) RCTPromiseRejectBlock reject;
492
+ @property (nonatomic, copy) NSString *capturesDirectory;
493
+ @end
494
+
495
+ @implementation InAppInspectorPickerDelegate
496
+
497
+ - (void)picker:(id)picker didFinishPicking:(NSArray *)results {
498
+ [picker dismissViewControllerAnimated:YES completion:nil];
499
+ if (results.count == 0) {
500
+ if (self.resolve) self.resolve([NSNull null]);
501
+ return;
502
+ }
503
+
504
+ id result = results.firstObject;
505
+ NSItemProvider *provider = [result valueForKey:@"itemProvider"];
506
+ long long timestamp = (long long)([[NSDate date] timeIntervalSince1970] * 1000.0);
507
+ NSString *randomStr = [NSString stringWithFormat:@"%04d", arc4random_uniform(10000)];
508
+
509
+ if ([provider hasItemConformingToTypeIdentifier:@"public.movie"]) {
510
+ [provider loadFileRepresentationForTypeIdentifier:@"public.movie" completionHandler:^(NSURL * _Nullable url, NSError * _Nullable error) {
511
+ if (error || !url) {
512
+ if (self.resolve) self.resolve([NSNull null]);
513
+ return;
514
+ }
515
+ NSString *ext = [url.pathExtension lowercaseString];
516
+ if (ext.length == 0) ext = @"mp4";
517
+ NSString *filename = [NSString stringWithFormat:@"rn_iai_%lld_imported_%@.%@", timestamp, randomStr, ext];
518
+ NSString *destPath = [self.capturesDirectory stringByAppendingPathComponent:filename];
519
+
520
+ [[NSFileManager defaultManager] removeItemAtPath:destPath error:nil];
521
+ [[NSFileManager defaultManager] copyItemAtURL:url toURL:[NSURL fileURLWithPath:destPath] error:nil];
522
+
523
+ NSDictionary *attrs = [[NSFileManager defaultManager] attributesOfItemAtPath:destPath error:nil];
524
+ long long sizeBytes = [attrs fileSize];
525
+
526
+ NSMutableDictionary *map = [NSMutableDictionary dictionaryWithDictionary:@{
527
+ @"id": filename,
528
+ @"type": @"video",
529
+ @"format": ext,
530
+ @"uri": [NSURL fileURLWithPath:destPath].absoluteString,
531
+ @"filename": filename,
532
+ @"sizeBytes": @(sizeBytes),
533
+ @"timestamp": @(timestamp)
534
+ }];
535
+
536
+ @try {
537
+ AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:[NSURL fileURLWithPath:destPath] options:nil];
538
+ AVAssetImageGenerator *gen = [[AVAssetImageGenerator alloc] initWithAsset:asset];
539
+ gen.appliesPreferredTrackTransform = YES;
540
+ CGImageRef cgImage = [gen copyCGImageAtTime:kCMTimeZero actualTime:NULL error:nil];
541
+ if (cgImage) {
542
+ UIImage *thumbImg = [UIImage imageWithCGImage:cgImage];
543
+ CGImageRelease(cgImage);
544
+ NSData *thumbData = UIImageJPEGRepresentation(thumbImg, 0.8);
545
+ NSString *thumbFile = [NSString stringWithFormat:@"rn_iai_%lld_imported_%@_thumb.jpg", timestamp, randomStr];
546
+ NSString *thumbPath = [self.capturesDirectory stringByAppendingPathComponent:thumbFile];
547
+ [thumbData writeToFile:thumbPath atomically:YES];
548
+ map[@"thumbnailUri"] = [NSURL fileURLWithPath:thumbPath].absoluteString;
549
+ }
550
+ } @catch (id ex) {}
551
+
552
+ if (self.resolve) self.resolve(map);
553
+ }];
554
+ } else {
555
+ [provider loadFileRepresentationForTypeIdentifier:@"public.image" completionHandler:^(NSURL * _Nullable url, NSError * _Nullable error) {
556
+ if (url) {
557
+ NSString *ext = [url.pathExtension lowercaseString];
558
+ if (ext.length == 0) ext = @"jpg";
559
+ NSString *type = [ext isEqualToString:@"gif"] ? @"gif" : @"image";
560
+ NSString *filename = [NSString stringWithFormat:@"rn_iai_%lld_imported_%@.%@", timestamp, randomStr, ext];
561
+ NSString *destPath = [self.capturesDirectory stringByAppendingPathComponent:filename];
562
+
563
+ [[NSFileManager defaultManager] removeItemAtPath:destPath error:nil];
564
+ [[NSFileManager defaultManager] copyItemAtURL:url toURL:[NSURL fileURLWithPath:destPath] error:nil];
565
+ NSDictionary *attrs = [[NSFileManager defaultManager] attributesOfItemAtPath:destPath error:nil];
566
+ long long sizeBytes = [attrs fileSize];
567
+
568
+ NSDictionary *map = @{
569
+ @"id": filename,
570
+ @"type": type,
571
+ @"format": ext,
572
+ @"uri": [NSURL fileURLWithPath:destPath].absoluteString,
573
+ @"filename": filename,
574
+ @"sizeBytes": @(sizeBytes),
575
+ @"timestamp": @(timestamp)
576
+ };
577
+ if (self.resolve) self.resolve(map);
578
+ } else {
579
+ [provider loadObjectOfClass:[UIImage class] completionHandler:^(id<NSItemProviderReading> _Nullable object, NSError * _Nullable err) {
580
+ if ([object isKindOfClass:[UIImage class]]) {
581
+ UIImage *img = (UIImage *)object;
582
+ NSData *data = UIImageJPEGRepresentation(img, 0.95);
583
+ NSString *filename = [NSString stringWithFormat:@"rn_iai_%lld_imported_%@.jpg", timestamp, randomStr];
584
+ NSString *destPath = [self.capturesDirectory stringByAppendingPathComponent:filename];
585
+ [data writeToFile:destPath atomically:YES];
586
+
587
+ NSDictionary *attrs = [[NSFileManager defaultManager] attributesOfItemAtPath:destPath error:nil];
588
+ long long sizeBytes = [attrs fileSize];
589
+
590
+ NSDictionary *map = @{
591
+ @"id": filename,
592
+ @"type": @"image",
593
+ @"format": @"jpg",
594
+ @"uri": [NSURL fileURLWithPath:destPath].absoluteString,
595
+ @"filename": filename,
596
+ @"sizeBytes": @(sizeBytes),
597
+ @"timestamp": @(timestamp)
598
+ };
599
+ if (self.resolve) self.resolve(map);
600
+ } else {
601
+ if (self.resolve) self.resolve([NSNull null]);
602
+ }
603
+ }];
604
+ }
605
+ }];
606
+ }
607
+ }
608
+
609
+ - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<UIImagePickerControllerInfoKey,id> *)info {
610
+ [picker dismissViewControllerAnimated:YES completion:nil];
611
+ if (self.resolve) self.resolve([NSNull null]);
612
+ }
613
+
614
+ - (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
615
+ [picker dismissViewControllerAnimated:YES completion:nil];
616
+ if (self.resolve) self.resolve([NSNull null]);
617
+ }
618
+
619
+ @end
620
+
621
+ static InAppInspectorPickerDelegate *g_pickerDelegate = nil;
622
+
484
623
  @implementation NetworkInspectorModule {
485
624
  bool hasListeners;
486
625
  CADisplayLink *displayLink;
@@ -1116,6 +1255,21 @@ RCT_EXPORT_METHOD(getNativeCachedPage:(NSString *)pageKey
1116
1255
  return capturesDir;
1117
1256
  }
1118
1257
 
1258
+ /**
1259
+ * Generates a filename in the format: rn_iai_{YYYYMMDD_HHmmss_SSS}_{fileType}_{random6}.{ext}
1260
+ */
1261
+ - (NSString *)generateCaptureFilename:(NSString *)fileType ext:(NSString *)ext {
1262
+ NSDateFormatter *df = [[NSDateFormatter alloc] init];
1263
+ [df setDateFormat:@"yyyyMMdd_HHmmss_SSS"];
1264
+ NSString *dateStamp = [df stringFromDate:[NSDate date]];
1265
+ NSString *chars = @"abcdefghijklmnopqrstuvwxyz0123456789";
1266
+ NSMutableString *random = [NSMutableString stringWithCapacity:6];
1267
+ for (int i = 0; i < 6; i++) {
1268
+ [random appendFormat:@"%C", [chars characterAtIndex:arc4random_uniform((uint32_t)chars.length)]];
1269
+ }
1270
+ return [NSString stringWithFormat:@"rn_iai_%@_%@_%@.%@", dateStamp, fileType, random, ext];
1271
+ }
1272
+
1119
1273
  - (UIWindow *)findActiveKeyWindow {
1120
1274
  UIWindow *foundWindow = nil;
1121
1275
  if (@available(iOS 13.0, *)) {
@@ -1283,7 +1437,7 @@ RCT_EXPORT_METHOD(getNativeCachedPage:(NSString *)pageKey
1283
1437
  CGSize videoSize = CGSizeMake(width, height);
1284
1438
  long long timestamp = (long long)([[NSDate date] timeIntervalSince1970] * 1000.0);
1285
1439
  self->_softwareRecordingTimestamp = timestamp;
1286
- NSString *filename = [NSString stringWithFormat:@"video_%lld.mp4", timestamp];
1440
+ NSString *filename = [self generateCaptureFilename:@"video" ext:@"mp4"];
1287
1441
  NSString *filePath = [[self getCapturesDirectory] stringByAppendingPathComponent:filename];
1288
1442
  NSURL *outputUrl = [NSURL fileURLWithPath:filePath];
1289
1443
 
@@ -1352,7 +1506,8 @@ RCT_EXPORT_METHOD(getNativeCachedPage:(NSString *)pageKey
1352
1506
  if (firstImg) {
1353
1507
  NSData *thumbData = UIImageJPEGRepresentation(firstImg, 0.8);
1354
1508
  if (thumbData) {
1355
- NSString *thumbFilename = [NSString stringWithFormat:@"thumb_%lld.jpg", timestamp];
1509
+ NSString *thumbBaseName = [[filename stringByDeletingPathExtension] stringByReplacingOccurrencesOfString:@"_video_" withString:@"_thumb_"];
1510
+ NSString *thumbFilename = [NSString stringWithFormat:@"%@.jpg", thumbBaseName];
1356
1511
  NSString *thumbFilePath = [[self getCapturesDirectory] stringByAppendingPathComponent:thumbFilename];
1357
1512
  [thumbData writeToFile:thumbFilePath atomically:YES];
1358
1513
  self->_softwareRecordingThumbnailPath = thumbFilePath;
@@ -1473,7 +1628,7 @@ RCT_EXPORT_METHOD(takeScreenshot:(NSDictionary *)options
1473
1628
  }
1474
1629
 
1475
1630
  long long timestamp = (long long)([[NSDate date] timeIntervalSince1970] * 1000.0);
1476
- NSString *filename = [NSString stringWithFormat:@"screenshot_%lld.%@", timestamp, ext];
1631
+ NSString *filename = [self generateCaptureFilename:@"screenshot" ext:ext];
1477
1632
  NSString *filePath = [[self getCapturesDirectory] stringByAppendingPathComponent:filename];
1478
1633
 
1479
1634
  [data writeToFile:filePath atomically:YES];
@@ -1571,7 +1726,7 @@ RCT_EXPORT_METHOD(stopVideoRecording:(RCTPromiseResolveBlock)resolve
1571
1726
  CGImageRelease(imgRef);
1572
1727
  NSData *tData = UIImageJPEGRepresentation(thumbImg, 0.85);
1573
1728
  if (tData) {
1574
- NSString *generatedThumbFile = [NSString stringWithFormat:@"thumb_%lld.jpg", timestamp];
1729
+ NSString *generatedThumbFile = [self generateCaptureFilename:@"thumb" ext:@"jpg"];
1575
1730
  NSString *generatedThumbPath = [[self getCapturesDirectory] stringByAppendingPathComponent:generatedThumbFile];
1576
1731
  [tData writeToFile:generatedThumbPath atomically:YES];
1577
1732
  result[@"thumbnailUri"] = [NSURL fileURLWithPath:generatedThumbPath].absoluteString;
@@ -1666,7 +1821,7 @@ RCT_EXPORT_METHOD(convertToGif:(NSString *)videoUri
1666
1821
  [reader startReading];
1667
1822
 
1668
1823
  long long timestamp = (long long)([[NSDate date] timeIntervalSince1970] * 1000.0);
1669
- NSString *filename = [NSString stringWithFormat:@"anim_%lld.gif", timestamp];
1824
+ NSString *filename = [self generateCaptureFilename:@"anim" ext:@"gif"];
1670
1825
  NSString *filePath = [[self getCapturesDirectory] stringByAppendingPathComponent:filename];
1671
1826
  NSURL *gifUrl = [NSURL fileURLWithPath:filePath];
1672
1827
 
@@ -1755,7 +1910,7 @@ RCT_EXPORT_METHOD(getCapturedMedia:(RCTPromiseResolveBlock)resolve
1755
1910
 
1756
1911
  for (NSString *file in (files ?: @[])) {
1757
1912
  // Skip standalone thumbnail files
1758
- if ([file hasPrefix:@"thumb_"]) continue;
1913
+ if ([file hasPrefix:@"thumb_"] || [file containsString:@"_thumb_"]) continue;
1759
1914
 
1760
1915
  NSString *fullPath = [dir stringByAppendingPathComponent:file];
1761
1916
  NSDictionary *attrs = [[NSFileManager defaultManager] attributesOfItemAtPath:fullPath error:nil];
@@ -1784,11 +1939,17 @@ RCT_EXPORT_METHOD(getCapturedMedia:(RCTPromiseResolveBlock)resolve
1784
1939
  }];
1785
1940
 
1786
1941
  if ([type isEqualToString:@"video"]) {
1787
- // Check if matching thumbnail exists
1942
+ // Try new naming convention: replace _video_ with _thumb_ in base name
1788
1943
  NSString *nameWithoutExt = [file stringByDeletingPathExtension];
1789
- NSString *timestampSuffix = [nameWithoutExt stringByReplacingOccurrencesOfString:@"video_" withString:@""];
1790
- NSString *thumbFile = [NSString stringWithFormat:@"thumb_%@.jpg", timestampSuffix];
1944
+ NSString *thumbBaseName = [nameWithoutExt stringByReplacingOccurrencesOfString:@"_video_" withString:@"_thumb_"];
1945
+ NSString *thumbFile = [NSString stringWithFormat:@"%@.jpg", thumbBaseName];
1791
1946
  NSString *thumbFullPath = [dir stringByAppendingPathComponent:thumbFile];
1947
+ // Fallback: legacy naming convention (thumb_{timestamp}.jpg)
1948
+ if (![[NSFileManager defaultManager] fileExistsAtPath:thumbFullPath]) {
1949
+ NSString *timestampSuffix = [nameWithoutExt stringByReplacingOccurrencesOfString:@"video_" withString:@""];
1950
+ thumbFile = [NSString stringWithFormat:@"thumb_%@.jpg", timestampSuffix];
1951
+ thumbFullPath = [dir stringByAppendingPathComponent:thumbFile];
1952
+ }
1792
1953
  if ([[NSFileManager defaultManager] fileExistsAtPath:thumbFullPath]) {
1793
1954
  item[@"thumbnailUri"] = [NSURL fileURLWithPath:thumbFullPath].absoluteString;
1794
1955
  } else {
@@ -1841,14 +2002,22 @@ RCT_EXPORT_METHOD(deleteCapturedMedia:(NSString *)uri
1841
2002
 
1842
2003
  // Also remove any related thumbnail
1843
2004
  NSString *filename = [path lastPathComponent];
1844
- if ([filename hasPrefix:@"video_"]) {
2005
+ if ([filename containsString:@"_video_"] || [filename hasPrefix:@"video_"]) {
1845
2006
  NSString *nameWithoutExt = [filename stringByDeletingPathExtension];
1846
- NSString *timestampSuffix = [nameWithoutExt stringByReplacingOccurrencesOfString:@"video_" withString:@""];
1847
- NSString *thumbFile = [NSString stringWithFormat:@"thumb_%@.jpg", timestampSuffix];
2007
+ // Try new convention: replace _video_ with _thumb_
2008
+ NSString *thumbBaseName = [nameWithoutExt stringByReplacingOccurrencesOfString:@"_video_" withString:@"_thumb_"];
2009
+ NSString *thumbFile = [NSString stringWithFormat:@"%@.jpg", thumbBaseName];
1848
2010
  NSString *thumbPath = [[path stringByDeletingLastPathComponent] stringByAppendingPathComponent:thumbFile];
1849
2011
  if ([[NSFileManager defaultManager] fileExistsAtPath:thumbPath]) {
1850
2012
  [[NSFileManager defaultManager] removeItemAtPath:thumbPath error:nil];
1851
2013
  }
2014
+ // Fallback: legacy convention
2015
+ NSString *timestampSuffix = [nameWithoutExt stringByReplacingOccurrencesOfString:@"video_" withString:@""];
2016
+ NSString *legacyThumbFile = [NSString stringWithFormat:@"thumb_%@.jpg", timestampSuffix];
2017
+ NSString *legacyThumbPath = [[path stringByDeletingLastPathComponent] stringByAppendingPathComponent:legacyThumbFile];
2018
+ if ([[NSFileManager defaultManager] fileExistsAtPath:legacyThumbPath]) {
2019
+ [[NSFileManager defaultManager] removeItemAtPath:legacyThumbPath error:nil];
2020
+ }
1852
2021
  }
1853
2022
 
1854
2023
  resolve(@(YES));
@@ -1920,241 +2089,241 @@ RCT_EXPORT_METHOD(editPhoto:(NSDictionary *)options
1920
2089
  resolve:(RCTPromiseResolveBlock)resolve
1921
2090
  reject:(RCTPromiseRejectBlock)reject) {
1922
2091
  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
1923
- @try {
1924
- NSString *rawUri = options[@"uri"];
1925
- if (!rawUri || rawUri.length == 0) {
1926
- reject(@"INVALID_URI", @"Image URI is missing or empty", nil);
1927
- return;
1928
- }
1929
-
1930
- NSString *cleanPath = rawUri;
1931
- if ([cleanPath hasPrefix:@"file://"]) {
1932
- cleanPath = [cleanPath substringFromIndex:7];
1933
- }
1934
- cleanPath = [cleanPath stringByRemovingPercentEncoding];
1935
-
1936
- UIImage *sourceImage = [UIImage imageWithContentsOfFile:cleanPath];
1937
- if (!sourceImage) {
1938
- reject(@"IMAGE_LOAD_FAILED", @"Failed to load source image", nil);
1939
- return;
1940
- }
2092
+ @autoreleasepool {
2093
+ @try {
2094
+ NSString *rawUri = options[@"uri"];
2095
+ if (!rawUri || rawUri.length == 0) {
2096
+ reject(@"INVALID_URI", @"Image URI is missing or empty", nil);
2097
+ return;
2098
+ }
1941
2099
 
1942
- // 1. Convert to CIImage
1943
- CIImage *ciImage = [CIImage imageWithCGImage:sourceImage.CGImage];
1944
- if (!ciImage) {
1945
- ciImage = [CIImage imageWithContentsOfURL:[NSURL fileURLWithPath:cleanPath]];
1946
- }
1947
- if (!ciImage) {
1948
- reject(@"CIIMAGE_FAILED", @"Failed to initialize CoreImage pipeline", nil);
1949
- return;
1950
- }
2100
+ NSString *cleanPath = rawUri;
2101
+ if ([cleanPath hasPrefix:@"file://"]) {
2102
+ cleanPath = [cleanPath substringFromIndex:7];
2103
+ }
2104
+ cleanPath = [cleanPath stringByRemovingPercentEncoding];
1951
2105
 
1952
- // 2. Apply Rotation & Flip
1953
- NSInteger rotation = [options[@"rotation"] integerValue];
1954
- BOOL flipH = [options[@"flipHorizontal"] boolValue];
1955
- BOOL flipV = [options[@"flipVertical"] boolValue];
1956
-
1957
- CGAffineTransform transform = CGAffineTransformIdentity;
1958
- if (rotation == 90) {
1959
- transform = CGAffineTransformRotate(transform, -M_PI_2);
1960
- } else if (rotation == 180) {
1961
- transform = CGAffineTransformRotate(transform, M_PI);
1962
- } else if (rotation == 270) {
1963
- transform = CGAffineTransformRotate(transform, M_PI_2);
1964
- }
1965
- if (flipH) {
1966
- transform = CGAffineTransformScale(transform, -1, 1);
1967
- }
1968
- if (flipV) {
1969
- transform = CGAffineTransformScale(transform, 1, -1);
1970
- }
1971
- if (!CGAffineTransformIsIdentity(transform)) {
1972
- ciImage = [ciImage imageByApplyingTransform:transform];
1973
- CGRect newExtent = ciImage.extent;
1974
- CGAffineTransform fixOrigin = CGAffineTransformMakeTranslation(-newExtent.origin.x, -newExtent.origin.y);
1975
- ciImage = [ciImage imageByApplyingTransform:fixOrigin];
1976
- }
2106
+ UIImage *sourceImage = [UIImage imageWithContentsOfFile:cleanPath];
2107
+ if (!sourceImage) {
2108
+ reject(@"IMAGE_LOAD_FAILED", @"Failed to load source image", nil);
2109
+ return;
2110
+ }
1977
2111
 
1978
- // 3. Apply Crop
1979
- NSDictionary *cropDict = options[@"crop"];
1980
- if (cropDict && [cropDict isKindOfClass:[NSDictionary class]]) {
1981
- CGFloat x = [cropDict[@"x"] doubleValue];
1982
- CGFloat y = [cropDict[@"y"] doubleValue];
1983
- CGFloat width = [cropDict[@"width"] doubleValue];
1984
- CGFloat height = [cropDict[@"height"] doubleValue];
1985
- BOOL isNorm = [cropDict[@"isNormalized"] boolValue];
1986
-
1987
- CGRect extent = ciImage.extent;
1988
- if (isNorm) {
1989
- x *= extent.size.width;
1990
- y *= extent.size.height;
1991
- width *= extent.size.width;
1992
- height *= extent.size.height;
2112
+ // 1. Convert to CIImage
2113
+ CIImage *ciImage = [CIImage imageWithCGImage:sourceImage.CGImage];
2114
+ if (!ciImage) {
2115
+ ciImage = [CIImage imageWithContentsOfURL:[NSURL fileURLWithPath:cleanPath]];
1993
2116
  }
1994
- // CoreImage coordinate system (bottom-left origin)
1995
- CGFloat ciY = extent.size.height - (y + height);
1996
- CGRect cropRect = CGRectMake(x, ciY, width, height);
1997
- CGRect intersection = CGRectIntersection(extent, cropRect);
1998
- if (!CGRectIsNull(intersection) && intersection.size.width > 0 && intersection.size.height > 0) {
1999
- ciImage = [ciImage imageByCroppingToRect:intersection];
2117
+ if (!ciImage) {
2118
+ reject(@"CIIMAGE_FAILED", @"Failed to initialize CoreImage pipeline", nil);
2119
+ return;
2000
2120
  }
2001
- }
2002
2121
 
2003
- // 4. Color Grading Adjustments (CIColorControls, CITemperatureAndTint, CIVignette)
2004
- NSDictionary *adjustments = options[@"adjustments"];
2005
- if (adjustments && [adjustments isKindOfClass:[NSDictionary class]]) {
2006
- NSNumber *brightness = adjustments[@"brightness"];
2007
- NSNumber *contrast = adjustments[@"contrast"];
2008
- NSNumber *saturation = adjustments[@"saturation"];
2009
-
2010
- if (brightness || contrast || saturation) {
2011
- CIFilter *colorControls = [CIFilter filterWithName:@"CIColorControls"];
2012
- [colorControls setValue:ciImage forKey:kCIInputImageKey];
2013
- if (brightness) [colorControls setValue:brightness forKey:kCIInputBrightnessKey];
2014
- if (contrast) [colorControls setValue:contrast forKey:kCIInputContrastKey];
2015
- if (saturation) [colorControls setValue:saturation forKey:kCIInputSaturationKey];
2016
- ciImage = colorControls.outputImage ?: ciImage;
2122
+ // 2. Apply Rotation & Flip
2123
+ NSInteger rotation = [options[@"rotation"] integerValue];
2124
+ BOOL flipH = [options[@"flipHorizontal"] boolValue];
2125
+ BOOL flipV = [options[@"flipVertical"] boolValue];
2126
+
2127
+ CGAffineTransform transform = CGAffineTransformIdentity;
2128
+ if (rotation == 90) {
2129
+ transform = CGAffineTransformRotate(transform, -M_PI_2);
2130
+ } else if (rotation == 180) {
2131
+ transform = CGAffineTransformRotate(transform, M_PI);
2132
+ } else if (rotation == 270) {
2133
+ transform = CGAffineTransformRotate(transform, M_PI_2);
2017
2134
  }
2018
-
2019
- NSNumber *temperature = adjustments[@"temperature"];
2020
- if (temperature && [temperature doubleValue] != 0) {
2021
- CIFilter *tempFilter = [CIFilter filterWithName:@"CITemperatureAndTint"];
2022
- [tempFilter setValue:ciImage forKey:kCIInputImageKey];
2023
- CIVector *neutral = [CIVector vectorWithX:6500 Y:0];
2024
- CGFloat shift = [temperature doubleValue] * 2000;
2025
- CIVector *target = [CIVector vectorWithX:6500 + shift Y:0];
2026
- [tempFilter setValue:neutral forKey:@"inputNeutral"];
2027
- [tempFilter setValue:target forKey:@"inputTargetNeutral"];
2028
- ciImage = tempFilter.outputImage ?: ciImage;
2135
+ if (flipH) {
2136
+ transform = CGAffineTransformScale(transform, -1, 1);
2137
+ }
2138
+ if (flipV) {
2139
+ transform = CGAffineTransformScale(transform, 1, -1);
2140
+ }
2141
+ if (!CGAffineTransformIsIdentity(transform)) {
2142
+ ciImage = [ciImage imageByApplyingTransform:transform];
2143
+ CGRect newExtent = ciImage.extent;
2144
+ CGAffineTransform fixOrigin = CGAffineTransformMakeTranslation(-newExtent.origin.x, -newExtent.origin.y);
2145
+ ciImage = [ciImage imageByApplyingTransform:fixOrigin];
2029
2146
  }
2030
2147
 
2031
- NSNumber *vignette = adjustments[@"vignette"];
2032
- if (vignette && [vignette doubleValue] > 0) {
2033
- CIFilter *vigFilter = [CIFilter filterWithName:@"CIVignette"];
2034
- [vigFilter setValue:ciImage forKey:kCIInputImageKey];
2035
- [vigFilter setValue:@([vignette doubleValue] * 2.0) forKey:kCIInputIntensityKey];
2036
- [vigFilter setValue:@(1.0) forKey:kCIInputRadiusKey];
2037
- ciImage = vigFilter.outputImage ?: ciImage;
2148
+ // 3. Apply Crop
2149
+ NSDictionary *cropDict = options[@"crop"];
2150
+ if (cropDict && [cropDict isKindOfClass:[NSDictionary class]]) {
2151
+ CGFloat x = [cropDict[@"x"] doubleValue];
2152
+ CGFloat y = [cropDict[@"y"] doubleValue];
2153
+ CGFloat width = [cropDict[@"width"] doubleValue];
2154
+ CGFloat height = [cropDict[@"height"] doubleValue];
2155
+ BOOL isNorm = [cropDict[@"isNormalized"] boolValue];
2156
+
2157
+ CGRect extent = ciImage.extent;
2158
+ if (isNorm) {
2159
+ x *= extent.size.width;
2160
+ y *= extent.size.height;
2161
+ width *= extent.size.width;
2162
+ height *= extent.size.height;
2163
+ }
2164
+ // CoreImage coordinate system (bottom-left origin)
2165
+ CGFloat ciY = extent.size.height - (y + height);
2166
+ CGRect cropRect = CGRectMake(x, ciY, width, height);
2167
+ CGRect intersection = CGRectIntersection(extent, cropRect);
2168
+ if (!CGRectIsNull(intersection) && intersection.size.width > 0 && intersection.size.height > 0) {
2169
+ ciImage = [ciImage imageByCroppingToRect:intersection];
2170
+ }
2038
2171
  }
2039
2172
 
2040
- NSNumber *sharpen = adjustments[@"sharpen"];
2041
- if (sharpen && [sharpen doubleValue] > 0) {
2042
- CIFilter *sharpFilter = [CIFilter filterWithName:@"CISharpenLuminance"];
2043
- [sharpFilter setValue:ciImage forKey:kCIInputImageKey];
2044
- [sharpFilter setValue:@([sharpen doubleValue] * 2.0) forKey:kCIInputSharpnessKey];
2045
- ciImage = sharpFilter.outputImage ?: ciImage;
2173
+ // 4. Color Grading Adjustments (CIColorControls, CITemperatureAndTint, CIVignette)
2174
+ NSDictionary *adjustments = options[@"adjustments"];
2175
+ if (adjustments && [adjustments isKindOfClass:[NSDictionary class]]) {
2176
+ NSNumber *brightness = adjustments[@"brightness"];
2177
+ NSNumber *contrast = adjustments[@"contrast"];
2178
+ NSNumber *saturation = adjustments[@"saturation"];
2179
+
2180
+ if (brightness || contrast || saturation) {
2181
+ CIFilter *colorControls = [CIFilter filterWithName:@"CIColorControls"];
2182
+ [colorControls setValue:ciImage forKey:kCIInputImageKey];
2183
+ if (brightness) [colorControls setValue:brightness forKey:kCIInputBrightnessKey];
2184
+ if (contrast) [colorControls setValue:contrast forKey:kCIInputContrastKey];
2185
+ if (saturation) [colorControls setValue:saturation forKey:kCIInputSaturationKey];
2186
+ ciImage = colorControls.outputImage ?: ciImage;
2187
+ }
2188
+
2189
+ NSNumber *temperature = adjustments[@"temperature"];
2190
+ if (temperature && [temperature doubleValue] != 0) {
2191
+ CIFilter *tempFilter = [CIFilter filterWithName:@"CITemperatureAndTint"];
2192
+ [tempFilter setValue:ciImage forKey:kCIInputImageKey];
2193
+ CIVector *neutral = [CIVector vectorWithX:6500 Y:0];
2194
+ CGFloat shift = [temperature doubleValue] * 2000;
2195
+ CIVector *target = [CIVector vectorWithX:6500 + shift Y:0];
2196
+ [tempFilter setValue:neutral forKey:@"inputNeutral"];
2197
+ [tempFilter setValue:target forKey:@"inputTargetNeutral"];
2198
+ ciImage = tempFilter.outputImage ?: ciImage;
2199
+ }
2200
+
2201
+ NSNumber *vignette = adjustments[@"vignette"];
2202
+ if (vignette && [vignette doubleValue] > 0) {
2203
+ CIFilter *vigFilter = [CIFilter filterWithName:@"CIVignette"];
2204
+ [vigFilter setValue:ciImage forKey:kCIInputImageKey];
2205
+ [vigFilter setValue:@([vignette doubleValue] * 2.0) forKey:kCIInputIntensityKey];
2206
+ [vigFilter setValue:@(1.0) forKey:kCIInputRadiusKey];
2207
+ ciImage = vigFilter.outputImage ?: ciImage;
2208
+ }
2209
+
2210
+ NSNumber *sharpen = adjustments[@"sharpen"];
2211
+ if (sharpen && [sharpen doubleValue] > 0) {
2212
+ CIFilter *sharpFilter = [CIFilter filterWithName:@"CISharpenLuminance"];
2213
+ [sharpFilter setValue:ciImage forKey:kCIInputImageKey];
2214
+ [sharpFilter setValue:@([sharpen doubleValue] * 2.0) forKey:kCIInputSharpnessKey];
2215
+ ciImage = sharpFilter.outputImage ?: ciImage;
2216
+ }
2046
2217
  }
2047
- }
2048
2218
 
2049
- // 5. Preset Filters
2050
- NSString *preset = options[@"filterPreset"];
2051
- if (preset && preset.length > 0 && ![preset isEqualToString:@"none"]) {
2052
- NSString *filterName = nil;
2053
- if ([preset isEqualToString:@"mono"]) filterName = @"CIPhotoEffectMono";
2054
- else if ([preset isEqualToString:@"noir"]) filterName = @"CIPhotoEffectNoir";
2055
- else if ([preset isEqualToString:@"sepia"]) filterName = @"CISepiaTone";
2056
- else if ([preset isEqualToString:@"vibrant"]) filterName = @"CIPhotoEffectChrome";
2057
- else if ([preset isEqualToString:@"fade"]) filterName = @"CIPhotoEffectFade";
2058
- else if ([preset isEqualToString:@"vintage"]) filterName = @"CIPhotoEffectInstant";
2059
-
2060
- if (filterName) {
2061
- CIFilter *pFilter = [CIFilter filterWithName:filterName];
2062
- [pFilter setValue:ciImage forKey:kCIInputImageKey];
2063
- ciImage = pFilter.outputImage ?: ciImage;
2219
+ // 5. Preset Filters
2220
+ NSString *preset = options[@"filterPreset"];
2221
+ if (preset && preset.length > 0 && ![preset isEqualToString:@"none"]) {
2222
+ NSString *filterName = nil;
2223
+ if ([preset isEqualToString:@"mono"]) filterName = @"CIPhotoEffectMono";
2224
+ else if ([preset isEqualToString:@"noir"]) filterName = @"CIPhotoEffectNoir";
2225
+ else if ([preset isEqualToString:@"sepia"]) filterName = @"CISepiaTone";
2226
+ else if ([preset isEqualToString:@"vibrant"]) filterName = @"CIPhotoEffectChrome";
2227
+ else if ([preset isEqualToString:@"fade"]) filterName = @"CIPhotoEffectFade";
2228
+ else if ([preset isEqualToString:@"vintage"]) filterName = @"CIPhotoEffectInstant";
2229
+
2230
+ if (filterName) {
2231
+ CIFilter *pFilter = [CIFilter filterWithName:filterName];
2232
+ [pFilter setValue:ciImage forKey:kCIInputImageKey];
2233
+ ciImage = pFilter.outputImage ?: ciImage;
2234
+ }
2064
2235
  }
2065
- }
2066
2236
 
2067
- // 6. GPU Render to File
2068
- CIContext *context = [CIContext contextWithOptions:@{kCIContextUseSoftwareRenderer: @(NO)}];
2069
- CGImageRef cgImage = [context createCGImage:ciImage fromRect:ciImage.extent];
2070
- if (!cgImage) {
2071
- reject(@"RENDER_FAILED", @"Failed to render CGImage", nil);
2072
- return;
2073
- }
2237
+ // 6. GPU Render to File
2238
+ CIContext *context = [CIContext contextWithOptions:@{kCIContextUseSoftwareRenderer: @(NO)}];
2239
+ CGImageRef cgImage = [context createCGImage:ciImage fromRect:ciImage.extent];
2240
+ if (!cgImage) {
2241
+ reject(@"RENDER_FAILED", @"Failed to render CGImage", nil);
2242
+ return;
2243
+ }
2074
2244
 
2075
- UIImage *resultImage = [UIImage imageWithCGImage:cgImage];
2076
- CGImageRelease(cgImage);
2077
-
2078
- // 7. Apply Redactions & Annotations Overlay if provided
2079
- NSArray *redactions = options[@"redactions"];
2080
- NSArray *annotations = options[@"annotations"];
2081
- if ((redactions && [redactions isKindOfClass:[NSArray class]] && redactions.count > 0) ||
2082
- (annotations && [annotations isKindOfClass:[NSArray class]] && annotations.count > 0)) {
2083
- UIGraphicsBeginImageContextWithOptions(resultImage.size, NO, 1.0);
2084
- [resultImage drawInRect:CGRectMake(0, 0, resultImage.size.width, resultImage.size.height)];
2085
- CGContextRef ctx = UIGraphicsGetCurrentContext();
2086
-
2087
- if (redactions && [redactions isKindOfClass:[NSArray class]]) {
2088
- for (NSDictionary *box in redactions) {
2089
- CGFloat x = [box[@"x"] doubleValue];
2090
- CGFloat y = [box[@"y"] doubleValue];
2091
- CGFloat w = [box[@"width"] doubleValue];
2092
- CGFloat h = [box[@"height"] doubleValue];
2093
- BOOL isNorm = [box[@"isNormalized"] boolValue];
2094
- if (isNorm) {
2095
- x *= resultImage.size.width;
2096
- y *= resultImage.size.height;
2097
- w *= resultImage.size.width;
2098
- h *= resultImage.size.height;
2245
+ UIImage *resultImage = [UIImage imageWithCGImage:cgImage];
2246
+ CGImageRelease(cgImage);
2247
+
2248
+ // 7. Apply Redactions & Annotations Overlay if provided
2249
+ NSArray *redactions = options[@"redactions"];
2250
+ NSArray *annotations = options[@"annotations"];
2251
+ if ((redactions && [redactions isKindOfClass:[NSArray class]] && redactions.count > 0) ||
2252
+ (annotations && [annotations isKindOfClass:[NSArray class]] && annotations.count > 0)) {
2253
+ UIGraphicsBeginImageContextWithOptions(resultImage.size, NO, 1.0);
2254
+ [resultImage drawInRect:CGRectMake(0, 0, resultImage.size.width, resultImage.size.height)];
2255
+ CGContextRef ctx = UIGraphicsGetCurrentContext();
2256
+
2257
+ if (redactions && [redactions isKindOfClass:[NSArray class]]) {
2258
+ for (NSDictionary *box in redactions) {
2259
+ CGFloat x = [box[@"x"] doubleValue];
2260
+ CGFloat y = [box[@"y"] doubleValue];
2261
+ CGFloat w = [box[@"width"] doubleValue];
2262
+ CGFloat h = [box[@"height"] doubleValue];
2263
+ BOOL isNorm = [box[@"isNormalized"] boolValue];
2264
+ if (isNorm) {
2265
+ x *= resultImage.size.width;
2266
+ y *= resultImage.size.height;
2267
+ w *= resultImage.size.width;
2268
+ h *= resultImage.size.height;
2269
+ }
2270
+ CGContextSetFillColorWithColor(ctx, [UIColor blackColor].CGColor);
2271
+ CGContextFillRect(ctx, CGRectMake(x, y, w, h));
2099
2272
  }
2100
- CGContextSetFillColorWithColor(ctx, [UIColor blackColor].CGColor);
2101
- CGContextFillRect(ctx, CGRectMake(x, y, w, h));
2102
2273
  }
2103
- }
2104
2274
 
2105
- if (annotations && [annotations isKindOfClass:[NSArray class]]) {
2106
- for (NSDictionary *ann in annotations) {
2107
- CGFloat x = [ann[@"x"] doubleValue];
2108
- CGFloat y = [ann[@"y"] doubleValue];
2109
- CGFloat w = [ann[@"width"] doubleValue];
2110
- CGFloat h = [ann[@"height"] doubleValue];
2111
- BOOL isNorm = [ann[@"isNormalized"] boolValue];
2112
- if (isNorm) {
2113
- x *= resultImage.size.width;
2114
- y *= resultImage.size.height;
2115
- w *= resultImage.size.width;
2116
- h *= resultImage.size.height;
2275
+ if (annotations && [annotations isKindOfClass:[NSArray class]]) {
2276
+ for (NSDictionary *ann in annotations) {
2277
+ CGFloat x = [ann[@"x"] doubleValue];
2278
+ CGFloat y = [ann[@"y"] doubleValue];
2279
+ CGFloat w = [ann[@"width"] doubleValue];
2280
+ CGFloat h = [ann[@"height"] doubleValue];
2281
+ BOOL isNorm = [ann[@"isNormalized"] boolValue];
2282
+ if (isNorm) {
2283
+ x *= resultImage.size.width;
2284
+ y *= resultImage.size.height;
2285
+ w *= resultImage.size.width;
2286
+ h *= resultImage.size.height;
2287
+ }
2288
+ CGContextSetStrokeColorWithColor(ctx, [UIColor redColor].CGColor);
2289
+ CGContextSetLineWidth(ctx, 4.0);
2290
+ CGContextStrokeRect(ctx, CGRectMake(x, y, w, h));
2117
2291
  }
2118
- CGContextSetStrokeColorWithColor(ctx, [UIColor redColor].CGColor);
2119
- CGContextSetLineWidth(ctx, 4.0);
2120
- CGContextStrokeRect(ctx, CGRectMake(x, y, w, h));
2121
2292
  }
2293
+
2294
+ resultImage = UIGraphicsGetImageFromCurrentImageContext();
2295
+ UIGraphicsEndImageContext();
2122
2296
  }
2123
2297
 
2124
- resultImage = UIGraphicsGetImageFromCurrentImageContext();
2125
- UIGraphicsEndImageContext();
2126
- }
2298
+ NSString *format = [options[@"format"] lowercaseString] ?: @"jpeg";
2299
+ CGFloat quality = options[@"quality"] ? [options[@"quality"] doubleValue] : 0.9;
2300
+ NSData *imageData = nil;
2301
+ NSString *ext = @"jpg";
2302
+ NSString *mime = @"image/jpeg";
2127
2303
 
2128
- NSString *format = [options[@"format"] lowercaseString] ?: @"jpeg";
2129
- CGFloat quality = options[@"quality"] ? [options[@"quality"] doubleValue] : 0.9;
2130
- NSData *imageData = nil;
2131
- NSString *ext = @"jpg";
2132
- NSString *mime = @"image/jpeg";
2304
+ if ([format isEqualToString:@"png"]) {
2305
+ imageData = UIImagePNGRepresentation(resultImage);
2306
+ ext = @"png";
2307
+ mime = @"image/png";
2308
+ } else {
2309
+ imageData = UIImageJPEGRepresentation(resultImage, quality);
2310
+ }
2133
2311
 
2134
- if ([format isEqualToString:@"png"]) {
2135
- imageData = UIImagePNGRepresentation(resultImage);
2136
- ext = @"png";
2137
- mime = @"image/png";
2138
- } else {
2139
- imageData = UIImageJPEGRepresentation(resultImage, quality);
2312
+ NSString *fileName = [self generateCaptureFilename:@"edit" ext:ext];
2313
+ NSString *outPath = [[self getCapturesDirectory] stringByAppendingPathComponent:fileName];
2314
+ [imageData writeToFile:outPath atomically:YES];
2315
+
2316
+ resolve(@{
2317
+ @"uri": [NSURL fileURLWithPath:outPath].absoluteString,
2318
+ @"width": @(resultImage.size.width),
2319
+ @"height": @(resultImage.size.height),
2320
+ @"size": @(imageData.length),
2321
+ @"mimeType": mime,
2322
+ @"format": format,
2323
+ });
2324
+ } @catch (NSException *ex) {
2325
+ reject(@"EDIT_FAILED", ex.reason ?: @"Photo edit failed", nil);
2140
2326
  }
2141
-
2142
- NSDateFormatter *df = [[NSDateFormatter alloc] init];
2143
- [df setDateFormat:@"yyyyMMdd_HHmmss_SSS"];
2144
- NSString *fileName = [NSString stringWithFormat:@"edit_%@.%@", [df stringFromDate:[NSDate date]], ext];
2145
- NSString *outPath = [[self getCapturesDirectory] stringByAppendingPathComponent:fileName];
2146
- [imageData writeToFile:outPath atomically:YES];
2147
-
2148
- resolve(@{
2149
- @"uri": [NSURL fileURLWithPath:outPath].absoluteString,
2150
- @"width": @(resultImage.size.width),
2151
- @"height": @(resultImage.size.height),
2152
- @"size": @(imageData.length),
2153
- @"mimeType": mime,
2154
- @"format": format,
2155
- });
2156
- } @catch (NSException *ex) {
2157
- reject(@"EDIT_FAILED", ex.reason ?: @"Photo edit failed", nil);
2158
2327
  }
2159
2328
  });
2160
2329
  }
@@ -2235,9 +2404,7 @@ RCT_EXPORT_METHOD(trimVideo:(NSDictionary *)options
2235
2404
  else if ([quality isEqualToString:@"low"]) preset = AVAssetExportPreset640x480;
2236
2405
 
2237
2406
  AVAssetExportSession *exportSession = [AVAssetExportSession exportSessionWithAsset:composition presetName:preset];
2238
- NSDateFormatter *df = [[NSDateFormatter alloc] init];
2239
- [df setDateFormat:@"yyyyMMdd_HHmmss_SSS"];
2240
- NSString *fileName = [NSString stringWithFormat:@"trim_%@.mp4", [df stringFromDate:[NSDate date]]];
2407
+ NSString *fileName = [self generateCaptureFilename:@"trim" ext:@"mp4"];
2241
2408
  NSString *outPath = [[self getCapturesDirectory] stringByAppendingPathComponent:fileName];
2242
2409
  NSURL *outUrl = [NSURL fileURLWithPath:outPath];
2243
2410
 
@@ -2340,6 +2507,102 @@ RCT_EXPORT_METHOD(generateFilmstrip:(NSDictionary *)options
2340
2507
  });
2341
2508
  }
2342
2509
 
2510
+ // ─────────────────────────────────────────────────────────────────────────────
2511
+ // NATIVE CAMERA ROLL / PHOTO & VIDEO PICKER
2512
+ // ─────────────────────────────────────────────────────────────────────────────
2513
+
2514
+ RCT_EXPORT_METHOD(pickMedia:(NSDictionary *)options
2515
+ resolve:(RCTPromiseResolveBlock)resolve
2516
+ reject:(RCTPromiseRejectBlock)reject) {
2517
+ dispatch_async(dispatch_get_main_queue(), ^{
2518
+ 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;
2544
+ }
2545
+
2546
+ g_pickerDelegate = [[InAppInspectorPickerDelegate alloc] init];
2547
+ g_pickerDelegate.resolve = resolve;
2548
+ g_pickerDelegate.reject = reject;
2549
+ 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
+
2564
+ if ([mediaType isEqualToString:@"image"]) {
2565
+ if ([PHPickerFilterClass respondsToSelector:imgFilterSel]) {
2566
+ filter = ((id (*)(id, SEL))objc_msgSend)(PHPickerFilterClass, imgFilterSel);
2567
+ }
2568
+ } else if ([mediaType isEqualToString:@"video"]) {
2569
+ if ([PHPickerFilterClass respondsToSelector:vidFilterSel]) {
2570
+ filter = ((id (*)(id, SEL))objc_msgSend)(PHPickerFilterClass, vidFilterSel);
2571
+ }
2572
+ } 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"];
2581
+ }
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"];
2587
+ [rootVC presentViewController:picker animated:YES completion:nil];
2588
+ } else {
2589
+ UIImagePickerController *picker = [[UIImagePickerController alloc] init];
2590
+ picker.delegate = g_pickerDelegate;
2591
+ #pragma clang diagnostic push
2592
+ #pragma clang diagnostic ignored "-Wdeprecated-declarations"
2593
+ if ([mediaType isEqualToString:@"image"]) {
2594
+ picker.mediaTypes = @[(NSString *)kUTTypeImage];
2595
+ } else if ([mediaType isEqualToString:@"video"]) {
2596
+ picker.mediaTypes = @[(NSString *)kUTTypeMovie];
2597
+ } else {
2598
+ picker.mediaTypes = @[(NSString *)kUTTypeImage, (NSString *)kUTTypeMovie];
2599
+ }
2600
+ #pragma clang diagnostic pop
2601
+ [rootVC presentViewController:picker animated:YES completion:nil];
2602
+ }
2603
+ });
2604
+ }
2605
+
2343
2606
 
2344
2607
  #ifdef RCT_NEW_ARCH_ENABLED
2345
2608
  - (std::shared_ptr<facebook::react::TurboModule>)getTurboModule: