react-native-inapp-inspector 2.3.18 → 2.3.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/src/main/java/com/inappinspector/NetworkInspectorModule.kt +57 -0
- package/dist/commonjs/analytics.js +1 -24
- package/dist/commonjs/bundle.js +1 -16
- package/dist/commonjs/capture.d.ts +2 -0
- package/dist/commonjs/capture.js +1 -32
- package/dist/commonjs/components/AnalyticsDetail.js +92 -623
- package/dist/commonjs/components/AnalyticsEventCard.js +54 -350
- package/dist/commonjs/components/AnalyticsGraph.js +70 -370
- package/dist/commonjs/components/AnimatedEntrance.js +1 -11
- package/dist/commonjs/components/AppHeaderLogo.js +7 -134
- package/dist/commonjs/components/BrandCircleIcon.js +73 -118
- package/dist/commonjs/components/BrandSquareIcon.js +63 -108
- package/dist/commonjs/components/CodeSnippet.js +48 -623
- package/dist/commonjs/components/ConsoleLogCard.js +63 -537
- package/dist/commonjs/components/CopyButton.js +3 -89
- package/dist/commonjs/components/DiffViewer.js +19 -83
- package/dist/commonjs/components/DomainHeader.js +27 -127
- package/dist/commonjs/components/EmptyState.d.ts +1 -0
- package/dist/commonjs/components/EmptyState.js +10 -87
- package/dist/commonjs/components/EndOfListFooter.js +7 -81
- package/dist/commonjs/components/ErrorBoundary.js +72 -566
- package/dist/commonjs/components/HeadersSection.js +31 -110
- package/dist/commonjs/components/HighlightText.js +17 -58
- package/dist/commonjs/components/Inspector/AboutModal.d.ts +6 -0
- package/dist/commonjs/components/Inspector/AboutModal.js +351 -0
- package/dist/commonjs/components/Inspector/AnalyticsFilterModal.js +98 -797
- package/dist/commonjs/components/Inspector/AnalyticsTab.js +284 -930
- package/dist/commonjs/components/Inspector/BundleTab.js +551 -2918
- package/dist/commonjs/components/Inspector/ConsoleTab.js +79 -492
- package/dist/commonjs/components/Inspector/CrashDetail.js +123 -672
- package/dist/commonjs/components/Inspector/CrashFilterModal.js +66 -498
- package/dist/commonjs/components/Inspector/CrashTab.js +98 -670
- package/dist/commonjs/components/Inspector/DebuggingTab.js +64 -871
- package/dist/commonjs/components/Inspector/DeviceInfoTab.js +143 -907
- package/dist/commonjs/components/Inspector/FabLauncher.js +85 -54
- package/dist/commonjs/components/Inspector/FeatureUnderDevNotice.js +6 -99
- package/dist/commonjs/components/Inspector/FeedbackModal.d.ts +9 -0
- package/dist/commonjs/components/Inspector/FeedbackModal.js +167 -521
- package/dist/commonjs/components/Inspector/InspectorContext.js +1 -21
- package/dist/commonjs/components/Inspector/InspectorHeader.js +219 -1093
- package/dist/commonjs/components/Inspector/LogDetail.js +168 -994
- package/dist/commonjs/components/Inspector/MainScreen.js +60 -332
- package/dist/commonjs/components/Inspector/MediaGalleryTab.js +136 -278
- package/dist/commonjs/components/Inspector/MediaPreviewModal.js +134 -361
- package/dist/commonjs/components/Inspector/NavigationTracker.js +1 -12
- package/dist/commonjs/components/Inspector/NetworkDetail.js +96 -432
- package/dist/commonjs/components/Inspector/NetworkFilterModal.js +60 -576
- package/dist/commonjs/components/Inspector/NetworkTab.js +84 -514
- package/dist/commonjs/components/Inspector/NpmStarPrompt.js +17 -433
- package/dist/commonjs/components/Inspector/NpmUpdateToast.js +25 -298
- package/dist/commonjs/components/Inspector/PerformanceTab.js +182 -1397
- package/dist/commonjs/components/Inspector/ReduxDetail.js +188 -1089
- package/dist/commonjs/components/Inspector/ReduxTab.js +85 -701
- package/dist/commonjs/components/Inspector/SettingsPanel.js +431 -3431
- package/dist/commonjs/components/Inspector/SkeletonPlaceholder.js +11 -180
- package/dist/commonjs/components/Inspector/StorageTab.js +93 -826
- package/dist/commonjs/components/Inspector/TabBar.js +47 -183
- package/dist/commonjs/components/Inspector/UpdateAvailableModal.js +34 -408
- package/dist/commonjs/components/JsonViewer.js +168 -380
- package/dist/commonjs/components/LogCard.js +57 -567
- package/dist/commonjs/components/LogSyntaxHighlighter.js +11 -130
- package/dist/commonjs/components/MetaAccordion.js +69 -238
- package/dist/commonjs/components/MiniBarChart.js +3 -56
- package/dist/commonjs/components/MiniLineChart.js +3 -58
- package/dist/commonjs/components/NetworkIcons.d.ts +7 -0
- package/dist/commonjs/components/NetworkIcons.js +479 -997
- package/dist/commonjs/components/QRCodeView.js +5 -79
- package/dist/commonjs/components/SectionHeader.js +15 -37
- package/dist/commonjs/components/SegmentedTabs.js +7 -61
- package/dist/commonjs/components/SkeletonPlaceholder.js +11 -180
- package/dist/commonjs/components/Slider.js +15 -243
- package/dist/commonjs/components/SourcePageCard.js +30 -89
- package/dist/commonjs/components/Toast.js +5 -147
- package/dist/commonjs/components/TouchableScale.js +3 -24
- package/dist/commonjs/components/TreeNode.js +55 -130
- package/dist/commonjs/console.js +1 -16
- package/dist/commonjs/constants/index.js +1 -32
- package/dist/commonjs/constants/telemetryConfig.js +1 -6
- package/dist/commonjs/constants/version.d.ts +1 -1
- package/dist/commonjs/constants/version.js +1 -4
- package/dist/commonjs/crash.js +1 -23
- package/dist/commonjs/customHooks/analyticsLogger.js +1 -250
- package/dist/commonjs/customHooks/bundleAnalyzer.js +1 -957
- package/dist/commonjs/customHooks/consoleLogger.js +6 -445
- package/dist/commonjs/customHooks/crashHandler.js +7 -656
- package/dist/commonjs/customHooks/logFilters.js +1 -23
- package/dist/commonjs/customHooks/networkLogger.js +2 -536
- package/dist/commonjs/customHooks/performanceTracker.js +63 -750
- package/dist/commonjs/customHooks/reduxLogger.js +2 -313
- package/dist/commonjs/customHooks/storageInspector.js +1 -435
- package/dist/commonjs/customHooks/useAccordion.js +1 -18
- package/dist/commonjs/decorators/index.js +1 -100
- package/dist/commonjs/helpers/gaAnalyticsRegistry.js +1 -148
- package/dist/commonjs/helpers/index.js +8 -921
- package/dist/commonjs/helpers/memoryManager.js +1 -99
- package/dist/commonjs/helpers/qrGenerator.js +1 -367
- package/dist/commonjs/helpers/remoteConfig.js +1 -165
- package/dist/commonjs/helpers/searchQueryParser.js +1 -62
- package/dist/commonjs/helpers/settingsStore.js +1 -144
- package/dist/commonjs/helpers/telemetry.js +1 -501
- package/dist/commonjs/helpers/toast.js +1 -20
- package/dist/commonjs/i18n/index.js +1 -90
- package/dist/commonjs/i18n/locales/en.json +1 -1122
- package/dist/commonjs/index.js +5 -2153
- package/dist/commonjs/metro.js +6 -468
- package/dist/commonjs/native/NativeInspector.d.ts +3 -0
- package/dist/commonjs/native/NativeInspector.js +1 -402
- package/dist/commonjs/native/NativeNetworkInspector.d.ts +1 -0
- package/dist/commonjs/native/NativeNetworkInspector.js +1 -4
- package/dist/commonjs/network.js +1 -13
- package/dist/commonjs/performance.js +1 -29
- package/dist/commonjs/redux.js +1 -20
- package/dist/commonjs/storage.js +1 -14
- package/dist/commonjs/styles/AppColors.js +1 -423
- package/dist/commonjs/styles/AppFonts.js +1 -17
- package/dist/commonjs/styles/common.js +1 -190
- package/dist/commonjs/styles/index.d.ts +6 -0
- package/dist/commonjs/styles/index.js +1 -1589
- package/dist/commonjs/types/enums.d.ts +2 -1
- package/dist/commonjs/types/enums.js +1 -150
- package/dist/commonjs/types/index.js +1 -18
- package/dist/commonjs/types/interfaces.d.ts +7 -0
- package/dist/commonjs/types/interfaces.js +1 -2
- package/dist/esm/analytics.js +1 -2
- package/dist/esm/bundle.js +1 -2
- package/dist/esm/capture.d.ts +2 -0
- package/dist/esm/capture.js +1 -29
- package/dist/esm/components/AnalyticsDetail.js +171 -664
- package/dist/esm/components/AnalyticsEventCard.js +77 -335
- package/dist/esm/components/AnalyticsGraph.js +95 -357
- package/dist/esm/components/AnimatedEntrance.js +1 -6
- package/dist/esm/components/AppHeaderLogo.js +7 -94
- package/dist/esm/components/BrandCircleIcon.js +114 -119
- package/dist/esm/components/BrandSquareIcon.js +73 -78
- package/dist/esm/components/CodeSnippet.js +58 -595
- package/dist/esm/components/ConsoleLogCard.js +91 -526
- package/dist/esm/components/CopyButton.js +3 -51
- package/dist/esm/components/DiffViewer.js +22 -48
- package/dist/esm/components/DomainHeader.js +43 -138
- package/dist/esm/components/EmptyState.d.ts +1 -0
- package/dist/esm/components/EmptyState.js +17 -56
- package/dist/esm/components/EndOfListFooter.js +15 -83
- package/dist/esm/components/ErrorBoundary.js +125 -582
- package/dist/esm/components/HeadersSection.js +52 -93
- package/dist/esm/components/HighlightText.js +17 -53
- package/dist/esm/components/Inspector/AboutModal.d.ts +6 -0
- package/dist/esm/components/Inspector/AboutModal.js +351 -0
- package/dist/esm/components/Inspector/AnalyticsFilterModal.js +225 -886
- package/dist/esm/components/Inspector/AnalyticsTab.js +296 -904
- package/dist/esm/components/Inspector/BundleTab.js +1175 -3502
- package/dist/esm/components/Inspector/ConsoleTab.js +113 -488
- package/dist/esm/components/Inspector/CrashDetail.js +236 -747
- package/dist/esm/components/Inspector/CrashFilterModal.js +149 -541
- package/dist/esm/components/Inspector/CrashTab.js +177 -711
- package/dist/esm/components/Inspector/DebuggingTab.js +156 -923
- package/dist/esm/components/Inspector/DeviceInfoTab.js +199 -924
- package/dist/esm/components/Inspector/FabLauncher.js +85 -49
- package/dist/esm/components/Inspector/FeatureUnderDevNotice.js +14 -70
- package/dist/esm/components/Inspector/FeedbackModal.d.ts +9 -0
- package/dist/esm/components/Inspector/FeedbackModal.js +182 -499
- package/dist/esm/components/Inspector/InspectorContext.js +1 -12
- package/dist/esm/components/Inspector/InspectorHeader.js +309 -1145
- package/dist/esm/components/Inspector/LogDetail.js +235 -1023
- package/dist/esm/components/Inspector/MainScreen.js +86 -320
- package/dist/esm/components/Inspector/MediaGalleryTab.js +157 -259
- package/dist/esm/components/Inspector/MediaPreviewModal.js +153 -340
- package/dist/esm/components/Inspector/NavigationTracker.js +1 -10
- package/dist/esm/components/Inspector/NetworkDetail.js +141 -472
- package/dist/esm/components/Inspector/NetworkFilterModal.js +122 -597
- package/dist/esm/components/Inspector/NetworkTab.js +125 -517
- package/dist/esm/components/Inspector/NpmStarPrompt.js +58 -434
- package/dist/esm/components/Inspector/NpmUpdateToast.js +45 -281
- package/dist/esm/components/Inspector/PerformanceTab.js +393 -1570
- package/dist/esm/components/Inspector/ReduxDetail.js +307 -1170
- package/dist/esm/components/Inspector/ReduxTab.js +144 -722
- package/dist/esm/components/Inspector/SettingsPanel.js +647 -3609
- package/dist/esm/components/Inspector/SkeletonPlaceholder.js +30 -163
- package/dist/esm/components/Inspector/StorageTab.js +172 -866
- package/dist/esm/components/Inspector/TabBar.js +52 -183
- package/dist/esm/components/Inspector/UpdateAvailableModal.js +79 -416
- package/dist/esm/components/JsonViewer.js +179 -353
- package/dist/esm/components/LogCard.js +93 -565
- package/dist/esm/components/LogSyntaxHighlighter.js +11 -123
- package/dist/esm/components/MetaAccordion.js +136 -267
- package/dist/esm/components/MiniBarChart.js +3 -18
- package/dist/esm/components/MiniLineChart.js +3 -20
- package/dist/esm/components/NetworkIcons.d.ts +7 -0
- package/dist/esm/components/NetworkIcons.js +481 -817
- package/dist/esm/components/QRCodeView.js +8 -45
- package/dist/esm/components/SectionHeader.js +22 -39
- package/dist/esm/components/SegmentedTabs.js +8 -57
- package/dist/esm/components/SkeletonPlaceholder.js +30 -163
- package/dist/esm/components/Slider.js +24 -213
- package/dist/esm/components/SourcePageCard.js +65 -86
- package/dist/esm/components/Toast.js +10 -117
- package/dist/esm/components/TouchableScale.js +3 -19
- package/dist/esm/components/TreeNode.js +58 -95
- package/dist/esm/console.js +1 -2
- package/dist/esm/constants/index.js +1 -28
- package/dist/esm/constants/telemetryConfig.js +1 -3
- package/dist/esm/constants/version.d.ts +1 -1
- package/dist/esm/constants/version.js +1 -1
- package/dist/esm/crash.js +1 -2
- package/dist/esm/customHooks/analyticsLogger.js +1 -230
- package/dist/esm/customHooks/bundleAnalyzer.js +1 -944
- package/dist/esm/customHooks/consoleLogger.js +6 -432
- package/dist/esm/customHooks/crashHandler.js +7 -630
- package/dist/esm/customHooks/logFilters.js +1 -20
- package/dist/esm/customHooks/networkLogger.js +2 -519
- package/dist/esm/customHooks/performanceTracker.js +63 -723
- package/dist/esm/customHooks/reduxLogger.js +2 -293
- package/dist/esm/customHooks/storageInspector.js +1 -418
- package/dist/esm/customHooks/useAccordion.js +1 -16
- package/dist/esm/decorators/index.js +1 -95
- package/dist/esm/helpers/gaAnalyticsRegistry.js +1 -143
- package/dist/esm/helpers/index.js +8 -861
- package/dist/esm/helpers/memoryManager.js +1 -91
- package/dist/esm/helpers/qrGenerator.js +1 -364
- package/dist/esm/helpers/remoteConfig.js +1 -160
- package/dist/esm/helpers/searchQueryParser.js +1 -59
- package/dist/esm/helpers/settingsStore.js +1 -134
- package/dist/esm/helpers/telemetry.js +1 -489
- package/dist/esm/helpers/toast.js +1 -15
- package/dist/esm/i18n/index.js +1 -78
- package/dist/esm/i18n/locales/en.json +1 -1122
- package/dist/esm/index.js +7 -1967
- package/dist/esm/metro.js +6 -459
- package/dist/esm/native/NativeInspector.d.ts +3 -0
- package/dist/esm/native/NativeInspector.js +1 -370
- package/dist/esm/native/NativeNetworkInspector.d.ts +1 -0
- package/dist/esm/native/NativeNetworkInspector.js +1 -2
- package/dist/esm/network.js +1 -1
- package/dist/esm/performance.js +1 -2
- package/dist/esm/redux.js +1 -1
- package/dist/esm/storage.js +1 -1
- package/dist/esm/styles/AppColors.js +1 -417
- package/dist/esm/styles/AppFonts.js +1 -13
- package/dist/esm/styles/common.js +1 -186
- package/dist/esm/styles/index.d.ts +6 -0
- package/dist/esm/styles/index.js +1 -1551
- package/dist/esm/types/enums.d.ts +2 -1
- package/dist/esm/types/enums.js +1 -147
- package/dist/esm/types/index.js +1 -2
- package/dist/esm/types/interfaces.d.ts +7 -0
- package/dist/esm/types/interfaces.js +1 -1
- package/ios/NetworkInspectorModule.mm +253 -136
- package/package.json +5 -3
- package/react-native-inapp-inspector.podspec +1 -1
- package/src/native/NativeInspector.ts +17 -0
- package/src/native/NativeNetworkInspector.ts +1 -0
- package/src/analytics.ts +0 -35
- package/src/bundle.ts +0 -25
- package/src/capture.ts +0 -101
- package/src/components/AnalyticsDetail.tsx +0 -870
- package/src/components/AnalyticsEventCard.tsx +0 -444
- package/src/components/AnalyticsGraph.tsx +0 -583
- package/src/components/AnimatedEntrance.tsx +0 -20
- package/src/components/AppHeaderLogo.tsx +0 -143
- package/src/components/BrandCircleIcon.tsx +0 -144
- package/src/components/BrandSquareIcon.tsx +0 -184
- package/src/components/CodeSnippet.tsx +0 -725
- package/src/components/ConsoleLogCard.tsx +0 -679
- package/src/components/CopyButton.tsx +0 -87
- package/src/components/DiffViewer.tsx +0 -82
- package/src/components/DomainHeader.tsx +0 -224
- package/src/components/EmptyState.tsx +0 -95
- package/src/components/EndOfListFooter.tsx +0 -100
- package/src/components/ErrorBoundary.tsx +0 -688
- package/src/components/HeadersSection.tsx +0 -172
- package/src/components/HighlightText.tsx +0 -100
- package/src/components/Inspector/AnalyticsFilterModal.tsx +0 -1250
- package/src/components/Inspector/AnalyticsTab.tsx +0 -1362
- package/src/components/Inspector/BundleTab.tsx +0 -4768
- package/src/components/Inspector/ConsoleTab.tsx +0 -726
- package/src/components/Inspector/CrashDetail.tsx +0 -997
- package/src/components/Inspector/CrashFilterModal.tsx +0 -721
- package/src/components/Inspector/CrashTab.tsx +0 -933
- package/src/components/Inspector/DebuggingTab.tsx +0 -1103
- package/src/components/Inspector/DeviceInfoTab.tsx +0 -1397
- package/src/components/Inspector/FabLauncher.tsx +0 -80
- package/src/components/Inspector/FeatureUnderDevNotice.tsx +0 -94
- package/src/components/Inspector/FeedbackModal.tsx +0 -626
- package/src/components/Inspector/InspectorContext.tsx +0 -28
- package/src/components/Inspector/InspectorHeader.tsx +0 -1545
- package/src/components/Inspector/LogDetail.tsx +0 -1431
- package/src/components/Inspector/MainScreen.tsx +0 -459
- package/src/components/Inspector/MediaGalleryTab.tsx +0 -355
- package/src/components/Inspector/MediaPreviewModal.tsx +0 -435
- package/src/components/Inspector/NavigationTracker.tsx +0 -13
- package/src/components/Inspector/NetworkDetail.tsx +0 -795
- package/src/components/Inspector/NetworkFilterModal.tsx +0 -730
- package/src/components/Inspector/NetworkTab.tsx +0 -820
- package/src/components/Inspector/NpmStarPrompt.tsx +0 -532
- package/src/components/Inspector/NpmUpdateToast.tsx +0 -387
- package/src/components/Inspector/PerformanceTab.tsx +0 -1967
- package/src/components/Inspector/ReduxDetail.tsx +0 -1651
- package/src/components/Inspector/ReduxTab.tsx +0 -987
- package/src/components/Inspector/SettingsPanel.tsx +0 -4580
- package/src/components/Inspector/SkeletonPlaceholder.tsx +0 -206
- package/src/components/Inspector/StorageTab.tsx +0 -1159
- package/src/components/Inspector/TabBar.tsx +0 -263
- package/src/components/Inspector/UpdateAvailableModal.tsx +0 -555
- package/src/components/JsonViewer.tsx +0 -547
- package/src/components/LogCard.tsx +0 -694
- package/src/components/LogSyntaxHighlighter.tsx +0 -178
- package/src/components/MetaAccordion.tsx +0 -355
- package/src/components/MiniBarChart.tsx +0 -42
- package/src/components/MiniLineChart.tsx +0 -33
- package/src/components/NetworkIcons.tsx +0 -2599
- package/src/components/QRCodeView.tsx +0 -75
- package/src/components/SectionHeader.tsx +0 -101
- package/src/components/SegmentedTabs.tsx +0 -83
- package/src/components/SkeletonPlaceholder.tsx +0 -206
- package/src/components/Slider.tsx +0 -300
- package/src/components/SourcePageCard.tsx +0 -150
- package/src/components/Toast.tsx +0 -131
- package/src/components/TouchableScale.tsx +0 -61
- package/src/components/TreeNode.tsx +0 -171
- package/src/console.ts +0 -24
- package/src/constants/index.ts +0 -41
- package/src/constants/telemetryConfig.ts +0 -4
- package/src/constants/version.ts +0 -3
- package/src/crash.ts +0 -32
- package/src/customHooks/analyticsLogger.ts +0 -336
- package/src/customHooks/bundleAnalyzer.ts +0 -1256
- package/src/customHooks/consoleLogger.ts +0 -530
- package/src/customHooks/crashHandler.ts +0 -944
- package/src/customHooks/logFilters.ts +0 -32
- package/src/customHooks/networkLogger.ts +0 -624
- package/src/customHooks/performanceTracker.ts +0 -1014
- package/src/customHooks/reduxLogger.ts +0 -406
- package/src/customHooks/storageInspector.ts +0 -513
- package/src/customHooks/useAccordion.tsx +0 -27
- package/src/decorators/index.ts +0 -184
- package/src/helpers/gaAnalyticsRegistry.ts +0 -204
- package/src/helpers/index.ts +0 -1092
- package/src/helpers/memoryManager.ts +0 -138
- package/src/helpers/qrGenerator.ts +0 -430
- package/src/helpers/remoteConfig.ts +0 -212
- package/src/helpers/searchQueryParser.ts +0 -84
- package/src/helpers/settingsStore.ts +0 -171
- package/src/helpers/telemetry.ts +0 -568
- package/src/helpers/toast.ts +0 -17
- package/src/i18n/index.ts +0 -104
- package/src/i18n/locales/en.json +0 -1125
- package/src/index.tsx +0 -2635
- package/src/metro.ts +0 -598
- package/src/network.ts +0 -22
- package/src/performance.ts +0 -38
- package/src/redux.ts +0 -23
- package/src/storage.ts +0 -18
- package/src/styles/AppColors.ts +0 -455
- package/src/styles/AppFonts.ts +0 -26
- package/src/styles/common.ts +0 -209
- package/src/styles/index.ts +0 -1606
- package/src/types/enums.ts +0 -208
- package/src/types/index.ts +0 -34
- package/src/types/interfaces.ts +0 -530
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
#import <unistd.h>
|
|
6
6
|
#import <ReplayKit/ReplayKit.h>
|
|
7
7
|
#import <AVFoundation/AVFoundation.h>
|
|
8
|
+
#import <AVKit/AVKit.h>
|
|
8
9
|
#import <ImageIO/ImageIO.h>
|
|
9
10
|
#import <MobileCoreServices/MobileCoreServices.h>
|
|
10
11
|
|
|
@@ -502,7 +503,11 @@ static void NativeExceptionHandler(NSException *exception) {
|
|
|
502
503
|
BOOL _isSoftwareRecordingActive;
|
|
503
504
|
NSInteger _softwareFrameIndex;
|
|
504
505
|
NSTimeInterval _softwareRecordingStartTime;
|
|
506
|
+
long long _softwareRecordingTimestamp;
|
|
505
507
|
NSString *_softwareRecordingFilePath;
|
|
508
|
+
NSString *_softwareRecordingThumbnailPath;
|
|
509
|
+
NSInteger _softwareVideoWidth;
|
|
510
|
+
NSInteger _softwareVideoHeight;
|
|
506
511
|
}
|
|
507
512
|
|
|
508
513
|
RCT_EXPORT_MODULE(NetworkInspectorModule);
|
|
@@ -1124,63 +1129,115 @@ RCT_EXPORT_METHOD(getNativeCachedPage:(NSString *)pageKey
|
|
|
1124
1129
|
return foundWindow;
|
|
1125
1130
|
}
|
|
1126
1131
|
|
|
1127
|
-
- (UIImage *)
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
bounds = [UIScreen mainScreen].bounds;
|
|
1132
|
+
- (UIImage *)captureScreenHierarchyWithScale:(CGFloat)scale {
|
|
1133
|
+
// Restrict capture strictly to active foreground app
|
|
1134
|
+
if ([UIApplication sharedApplication].applicationState != UIApplicationStateActive) {
|
|
1135
|
+
return nil;
|
|
1132
1136
|
}
|
|
1137
|
+
|
|
1138
|
+
CGRect screenBounds = [UIScreen mainScreen].bounds;
|
|
1133
1139
|
CGFloat screenScale = [UIScreen mainScreen].scale;
|
|
1134
1140
|
CGFloat finalScale = screenScale * scale;
|
|
1135
1141
|
if (finalScale <= 0.0) finalScale = screenScale;
|
|
1136
1142
|
|
|
1137
|
-
UIGraphicsBeginImageContextWithOptions(
|
|
1143
|
+
UIGraphicsBeginImageContextWithOptions(screenBounds.size, NO, finalScale);
|
|
1138
1144
|
CGContextRef context = UIGraphicsGetCurrentContext();
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
@
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
+
|
|
1146
|
+
NSArray<UIWindow *> *windows = @[];
|
|
1147
|
+
if (@available(iOS 13.0, *)) {
|
|
1148
|
+
NSMutableArray *allWindows = [NSMutableArray array];
|
|
1149
|
+
for (UIScene *scene in [UIApplication sharedApplication].connectedScenes) {
|
|
1150
|
+
if ([scene isKindOfClass:[UIWindowScene class]]) {
|
|
1151
|
+
[allWindows addObjectsFromArray:((UIWindowScene *)scene).windows];
|
|
1152
|
+
}
|
|
1153
|
+
}
|
|
1154
|
+
windows = allWindows;
|
|
1145
1155
|
}
|
|
1146
|
-
|
|
1147
|
-
|
|
1156
|
+
if (windows.count == 0) {
|
|
1157
|
+
#pragma clang diagnostic push
|
|
1158
|
+
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
|
1159
|
+
windows = [UIApplication sharedApplication].windows;
|
|
1160
|
+
#pragma clang diagnostic pop
|
|
1161
|
+
}
|
|
1162
|
+
|
|
1163
|
+
NSArray<UIWindow *> *sortedWindows = [windows sortedArrayUsingComparator:^NSComparisonResult(UIWindow *w1, UIWindow *w2) {
|
|
1164
|
+
if (w1.windowLevel < w2.windowLevel) return NSOrderedAscending;
|
|
1165
|
+
if (w1.windowLevel > w2.windowLevel) return NSOrderedDescending;
|
|
1166
|
+
return NSOrderedSame;
|
|
1167
|
+
}];
|
|
1168
|
+
|
|
1169
|
+
BOOL drewAny = NO;
|
|
1170
|
+
for (UIWindow *w in sortedWindows) {
|
|
1171
|
+
if (w.hidden || w.alpha <= 0.01 || w.bounds.size.width <= 0) continue;
|
|
1148
1172
|
@try {
|
|
1149
|
-
[
|
|
1150
|
-
|
|
1173
|
+
BOOL ok = [w drawViewHierarchyInRect:w.bounds afterScreenUpdates:NO];
|
|
1174
|
+
if (ok) {
|
|
1175
|
+
drewAny = YES;
|
|
1176
|
+
} else if (context) {
|
|
1177
|
+
[w.layer renderInContext:context];
|
|
1178
|
+
drewAny = YES;
|
|
1179
|
+
}
|
|
1180
|
+
} @catch (NSException *e) {
|
|
1181
|
+
if (context) {
|
|
1182
|
+
@try {
|
|
1183
|
+
[w.layer renderInContext:context];
|
|
1184
|
+
drewAny = YES;
|
|
1185
|
+
} @catch (NSException *ex) {}
|
|
1186
|
+
}
|
|
1187
|
+
}
|
|
1151
1188
|
}
|
|
1152
|
-
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
|
|
1153
|
-
UIGraphicsEndImageContext();
|
|
1154
1189
|
|
|
1155
|
-
if (!
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
if (ctx) {
|
|
1190
|
+
if (!drewAny) {
|
|
1191
|
+
UIWindow *fallback = [self findActiveKeyWindow];
|
|
1192
|
+
if (fallback && fallback.rootViewController && fallback.rootViewController.view && context) {
|
|
1159
1193
|
@try {
|
|
1160
|
-
[
|
|
1194
|
+
[fallback.rootViewController.view.layer renderInContext:context];
|
|
1161
1195
|
} @catch (NSException *e) {}
|
|
1162
1196
|
}
|
|
1163
|
-
image = UIGraphicsGetImageFromCurrentImageContext();
|
|
1164
|
-
UIGraphicsEndImageContext();
|
|
1165
1197
|
}
|
|
1198
|
+
|
|
1199
|
+
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
|
|
1200
|
+
UIGraphicsEndImageContext();
|
|
1166
1201
|
return image;
|
|
1167
1202
|
}
|
|
1168
1203
|
|
|
1169
|
-
- (
|
|
1204
|
+
- (UIImage *)captureWindowImage:(UIWindow *)window scale:(CGFloat)scale {
|
|
1205
|
+
return [self captureScreenHierarchyWithScale:scale];
|
|
1206
|
+
}
|
|
1207
|
+
|
|
1208
|
+
- (CVPixelBufferRef)createPixelBufferFromUIImage:(UIImage *)image size:(CGSize)size {
|
|
1209
|
+
if (!image) return NULL;
|
|
1210
|
+
CGImageRef cgImage = image.CGImage;
|
|
1211
|
+
if (!cgImage) return NULL;
|
|
1212
|
+
|
|
1170
1213
|
NSDictionary *options = @{
|
|
1171
1214
|
(id)kCVPixelBufferCGImageCompatibilityKey: @(YES),
|
|
1172
1215
|
(id)kCVPixelBufferCGBitmapContextCompatibilityKey: @(YES)
|
|
1173
1216
|
};
|
|
1174
1217
|
CVPixelBufferRef pxbuffer = NULL;
|
|
1175
|
-
CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault,
|
|
1218
|
+
CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault,
|
|
1219
|
+
(size_t)size.width,
|
|
1220
|
+
(size_t)size.height,
|
|
1221
|
+
kCVPixelFormatType_32BGRA,
|
|
1222
|
+
(__bridge CFDictionaryRef)options,
|
|
1223
|
+
&pxbuffer);
|
|
1176
1224
|
if (status != kCVReturnSuccess || pxbuffer == NULL) return NULL;
|
|
1177
1225
|
|
|
1178
1226
|
CVPixelBufferLockBaseAddress(pxbuffer, 0);
|
|
1179
1227
|
void *pxdata = CVPixelBufferGetBaseAddress(pxbuffer);
|
|
1228
|
+
size_t bytesPerRow = CVPixelBufferGetBytesPerRow(pxbuffer);
|
|
1180
1229
|
CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();
|
|
1181
|
-
CGContextRef context = CGBitmapContextCreate(pxdata,
|
|
1230
|
+
CGContextRef context = CGBitmapContextCreate(pxdata,
|
|
1231
|
+
(size_t)size.width,
|
|
1232
|
+
(size_t)size.height,
|
|
1233
|
+
8,
|
|
1234
|
+
bytesPerRow,
|
|
1235
|
+
rgbColorSpace,
|
|
1236
|
+
(CGBitmapInfo)kCGBitmapByteOrder32Little | (CGBitmapInfo)kCGImageAlphaPremultipliedFirst);
|
|
1182
1237
|
if (context) {
|
|
1183
|
-
|
|
1238
|
+
CGContextTranslateCTM(context, 0, size.height);
|
|
1239
|
+
CGContextScaleCTM(context, 1.0, -1.0);
|
|
1240
|
+
CGContextDrawImage(context, CGRectMake(0, 0, size.width, size.height), cgImage);
|
|
1184
1241
|
CGContextRelease(context);
|
|
1185
1242
|
}
|
|
1186
1243
|
CGColorSpaceRelease(rgbColorSpace);
|
|
@@ -1192,21 +1249,21 @@ RCT_EXPORT_METHOD(getNativeCachedPage:(NSString *)pageKey
|
|
|
1192
1249
|
resolve:(RCTPromiseResolveBlock)resolve
|
|
1193
1250
|
reject:(RCTPromiseRejectBlock)reject {
|
|
1194
1251
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1252
|
+
CGRect bounds = [UIScreen mainScreen].bounds;
|
|
1253
|
+
CGFloat screenScale = [UIScreen mainScreen].scale;
|
|
1254
|
+
double scaleParam = [options[@"scale"] doubleValue];
|
|
1255
|
+
if (scaleParam <= 0.0 || scaleParam > 1.0) {
|
|
1256
|
+
scaleParam = 0.5;
|
|
1199
1257
|
}
|
|
1200
1258
|
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
NSInteger width = ((NSInteger)(bounds.size.width * screenScale * 0.5) / 2) * 2;
|
|
1204
|
-
NSInteger height = ((NSInteger)(bounds.size.height * screenScale * 0.5) / 2) * 2;
|
|
1259
|
+
NSInteger width = ((NSInteger)(bounds.size.width * screenScale * scaleParam) / 2) * 2;
|
|
1260
|
+
NSInteger height = ((NSInteger)(bounds.size.height * screenScale * scaleParam) / 2) * 2;
|
|
1205
1261
|
if (width <= 0) width = 360;
|
|
1206
1262
|
if (height <= 0) height = 640;
|
|
1207
1263
|
|
|
1208
1264
|
CGSize videoSize = CGSizeMake(width, height);
|
|
1209
1265
|
long long timestamp = (long long)([[NSDate date] timeIntervalSince1970] * 1000.0);
|
|
1266
|
+
self->_softwareRecordingTimestamp = timestamp;
|
|
1210
1267
|
NSString *filename = [NSString stringWithFormat:@"video_%lld.mp4", timestamp];
|
|
1211
1268
|
NSString *filePath = [[self getCapturesDirectory] stringByAppendingPathComponent:filename];
|
|
1212
1269
|
NSURL *outputUrl = [NSURL fileURLWithPath:filePath];
|
|
@@ -1228,7 +1285,7 @@ RCT_EXPORT_METHOD(getNativeCachedPage:(NSString *)pageKey
|
|
|
1228
1285
|
self->_softwareWriterInput.expectsMediaDataInRealTime = YES;
|
|
1229
1286
|
|
|
1230
1287
|
NSDictionary *sourcePixelBufferAttributes = @{
|
|
1231
|
-
(id)kCVPixelBufferPixelFormatTypeKey: @(
|
|
1288
|
+
(id)kCVPixelBufferPixelFormatTypeKey: @(kCVPixelFormatType_32BGRA),
|
|
1232
1289
|
(id)kCVPixelBufferWidthKey: @(videoSize.width),
|
|
1233
1290
|
(id)kCVPixelBufferHeightKey: @(videoSize.height)
|
|
1234
1291
|
};
|
|
@@ -1246,14 +1303,37 @@ RCT_EXPORT_METHOD(getNativeCachedPage:(NSString *)pageKey
|
|
|
1246
1303
|
self->_softwareFrameIndex = 0;
|
|
1247
1304
|
self->_softwareRecordingStartTime = [[NSDate date] timeIntervalSince1970];
|
|
1248
1305
|
self->_softwareRecordingFilePath = filePath;
|
|
1306
|
+
self->_softwareVideoWidth = width;
|
|
1307
|
+
self->_softwareVideoHeight = height;
|
|
1249
1308
|
|
|
1250
1309
|
double fps = [options[@"fps"] doubleValue];
|
|
1251
1310
|
if (fps <= 0.0 || fps > 30.0) fps = 15.0;
|
|
1252
1311
|
double frameInterval = 1.0 / fps;
|
|
1253
1312
|
|
|
1313
|
+
// Immediately capture frame 0 & save thumbnail
|
|
1314
|
+
UIImage *firstImg = [self captureScreenHierarchyWithScale:(CGFloat)scaleParam];
|
|
1315
|
+
if (firstImg) {
|
|
1316
|
+
NSData *thumbData = UIImageJPEGRepresentation(firstImg, 0.8);
|
|
1317
|
+
if (thumbData) {
|
|
1318
|
+
NSString *thumbFilename = [NSString stringWithFormat:@"thumb_%lld.jpg", timestamp];
|
|
1319
|
+
NSString *thumbFilePath = [[self getCapturesDirectory] stringByAppendingPathComponent:thumbFilename];
|
|
1320
|
+
[thumbData writeToFile:thumbFilePath atomically:YES];
|
|
1321
|
+
self->_softwareRecordingThumbnailPath = thumbFilePath;
|
|
1322
|
+
}
|
|
1323
|
+
|
|
1324
|
+
if (self->_softwareWriterInput.isReadyForMoreMediaData) {
|
|
1325
|
+
CVPixelBufferRef buffer = [self createPixelBufferFromUIImage:firstImg size:videoSize];
|
|
1326
|
+
if (buffer) {
|
|
1327
|
+
[self->_softwarePixelBufferAdaptor appendPixelBuffer:buffer withPresentationTime:kCMTimeZero];
|
|
1328
|
+
CVPixelBufferRelease(buffer);
|
|
1329
|
+
self->_softwareFrameIndex = 1;
|
|
1330
|
+
}
|
|
1331
|
+
}
|
|
1332
|
+
}
|
|
1333
|
+
|
|
1254
1334
|
dispatch_queue_t queue = dispatch_queue_create("com.inappinspector.recording", DISPATCH_QUEUE_SERIAL);
|
|
1255
1335
|
self->_softwareRecordingTimerSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
|
|
1256
|
-
dispatch_source_set_timer(self->_softwareRecordingTimerSource, dispatch_time(DISPATCH_TIME_NOW,
|
|
1336
|
+
dispatch_source_set_timer(self->_softwareRecordingTimerSource, dispatch_time(DISPATCH_TIME_NOW, (int64_t)(frameInterval * NSEC_PER_SEC)), (uint64_t)(frameInterval * NSEC_PER_SEC), (uint64_t)(frameInterval * 0.1 * NSEC_PER_SEC));
|
|
1257
1337
|
|
|
1258
1338
|
__weak NetworkInspectorModule *weakSelf = self;
|
|
1259
1339
|
dispatch_source_set_event_handler(self->_softwareRecordingTimerSource, ^{
|
|
@@ -1262,10 +1342,11 @@ RCT_EXPORT_METHOD(getNativeCachedPage:(NSString *)pageKey
|
|
|
1262
1342
|
|
|
1263
1343
|
dispatch_sync(dispatch_get_main_queue(), ^{
|
|
1264
1344
|
if (!strongSelf || !strongSelf->_isSoftwareRecordingActive) return;
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1345
|
+
if (!strongSelf->_softwareAssetWriter || strongSelf->_softwareAssetWriter.status != AVAssetWriterStatusWriting) return;
|
|
1346
|
+
|
|
1347
|
+
UIImage *frameImg = [strongSelf captureScreenHierarchyWithScale:(CGFloat)scaleParam];
|
|
1348
|
+
if (frameImg && strongSelf->_softwareWriterInput.isReadyForMoreMediaData) {
|
|
1349
|
+
CVPixelBufferRef buffer = [strongSelf createPixelBufferFromUIImage:frameImg size:videoSize];
|
|
1269
1350
|
if (buffer) {
|
|
1270
1351
|
CMTime presentTime = CMTimeMake((int64_t)(strongSelf->_softwareFrameIndex * 1000 / fps), 1000);
|
|
1271
1352
|
[strongSelf->_softwarePixelBufferAdaptor appendPixelBuffer:buffer withPresentationTime:presentTime];
|
|
@@ -1286,18 +1367,12 @@ RCT_EXPORT_METHOD(takeScreenshot:(NSDictionary *)options
|
|
|
1286
1367
|
reject:(RCTPromiseRejectBlock)reject) {
|
|
1287
1368
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
1288
1369
|
@try {
|
|
1289
|
-
UIWindow *keyWindow = [self findActiveKeyWindow];
|
|
1290
|
-
if (!keyWindow) {
|
|
1291
|
-
reject(@"SCREENSHOT_ERROR", @"Unable to find active UIWindow for screen capture", nil);
|
|
1292
|
-
return;
|
|
1293
|
-
}
|
|
1294
|
-
|
|
1295
1370
|
double scaleParam = [options[@"scale"] doubleValue];
|
|
1296
1371
|
if (scaleParam <= 0.0 || scaleParam > 1.0) {
|
|
1297
1372
|
scaleParam = 1.0;
|
|
1298
1373
|
}
|
|
1299
1374
|
|
|
1300
|
-
UIImage *image = [self
|
|
1375
|
+
UIImage *image = [self captureScreenHierarchyWithScale:(CGFloat)scaleParam];
|
|
1301
1376
|
if (!image) {
|
|
1302
1377
|
reject(@"SCREENSHOT_ERROR", @"Failed to render window hierarchy to image context", nil);
|
|
1303
1378
|
return;
|
|
@@ -1358,96 +1433,40 @@ RCT_EXPORT_METHOD(takeScreenshot:(NSDictionary *)options
|
|
|
1358
1433
|
RCT_EXPORT_METHOD(startVideoRecording:(NSDictionary *)options
|
|
1359
1434
|
resolve:(RCTPromiseResolveBlock)resolve
|
|
1360
1435
|
reject:(RCTPromiseRejectBlock)reject) {
|
|
1361
|
-
if (self->_isSoftwareRecordingActive
|
|
1436
|
+
if (self->_isSoftwareRecordingActive) {
|
|
1362
1437
|
resolve(@(YES));
|
|
1363
1438
|
return;
|
|
1364
1439
|
}
|
|
1365
1440
|
|
|
1366
|
-
|
|
1367
|
-
if (recorder.isAvailable) {
|
|
1368
|
-
NSString *audioSource = [options[@"audioSource"] isKindOfClass:[NSString class]] ? options[@"audioSource"] : @"none";
|
|
1369
|
-
BOOL enableMic = [audioSource isEqualToString:@"mic"] || [audioSource isEqualToString:@"mixed"];
|
|
1370
|
-
recorder.microphoneEnabled = enableMic;
|
|
1371
|
-
|
|
1372
|
-
[recorder startRecordingWithHandler:^(NSError * _Nullable error) {
|
|
1373
|
-
if (error) {
|
|
1374
|
-
// If ReplayKit fails to initialize (e.g. simulator or sandbox), fallback to software frame recorder
|
|
1375
|
-
[self startSoftwareRecordingWithOptions:options resolve:resolve reject:reject];
|
|
1376
|
-
} else {
|
|
1377
|
-
resolve(@(YES));
|
|
1378
|
-
}
|
|
1379
|
-
}];
|
|
1380
|
-
} else {
|
|
1381
|
-
// Fallback to software frame recorder (works everywhere including iOS Simulators)
|
|
1382
|
-
[self startSoftwareRecordingWithOptions:options resolve:resolve reject:reject];
|
|
1383
|
-
}
|
|
1441
|
+
[self startSoftwareRecordingWithOptions:options resolve:resolve reject:reject];
|
|
1384
1442
|
}
|
|
1385
1443
|
|
|
1386
1444
|
RCT_EXPORT_METHOD(stopVideoRecording:(RCTPromiseResolveBlock)resolve
|
|
1387
1445
|
reject:(RCTPromiseRejectBlock)reject) {
|
|
1388
|
-
if (self->_isSoftwareRecordingActive) {
|
|
1389
|
-
self->_isSoftwareRecordingActive = NO;
|
|
1390
|
-
if (self->_softwareRecordingTimerSource) {
|
|
1391
|
-
dispatch_source_cancel(self->_softwareRecordingTimerSource);
|
|
1392
|
-
self->_softwareRecordingTimerSource = nil;
|
|
1393
|
-
}
|
|
1394
|
-
|
|
1395
|
-
[self->_softwareWriterInput markAsFinished];
|
|
1396
|
-
NSString *filePath = self->_softwareRecordingFilePath;
|
|
1397
|
-
NSTimeInterval duration = [[NSDate date] timeIntervalSince1970] - self->_softwareRecordingStartTime;
|
|
1398
|
-
long long timestamp = (long long)(self->_softwareRecordingStartTime * 1000.0);
|
|
1399
|
-
|
|
1400
|
-
[self->_softwareAssetWriter finishWritingWithCompletionHandler:^{
|
|
1401
|
-
self->_softwareAssetWriter = nil;
|
|
1402
|
-
self->_softwareWriterInput = nil;
|
|
1403
|
-
self->_softwarePixelBufferAdaptor = nil;
|
|
1404
|
-
|
|
1405
|
-
unsigned long long fileSize = 0;
|
|
1406
|
-
NSDictionary *attrs = [[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:nil];
|
|
1407
|
-
if (attrs) {
|
|
1408
|
-
fileSize = [attrs fileSize];
|
|
1409
|
-
}
|
|
1410
|
-
|
|
1411
|
-
NSDictionary *result = @{
|
|
1412
|
-
@"uri": [NSURL fileURLWithPath:filePath].absoluteString,
|
|
1413
|
-
@"format": @"mp4",
|
|
1414
|
-
@"durationMs": @(MAX(500.0, duration * 1000.0)),
|
|
1415
|
-
@"hasAudio": @(NO),
|
|
1416
|
-
@"width": @(720),
|
|
1417
|
-
@"height": @(1280),
|
|
1418
|
-
@"sizeBytes": @(fileSize),
|
|
1419
|
-
@"timestamp": @(timestamp)
|
|
1420
|
-
};
|
|
1421
|
-
resolve(result);
|
|
1422
|
-
}];
|
|
1423
|
-
return;
|
|
1424
|
-
}
|
|
1425
|
-
|
|
1426
|
-
RPScreenRecorder *recorder = [RPScreenRecorder sharedRecorder];
|
|
1427
|
-
if (!recorder.isRecording) {
|
|
1446
|
+
if (!self->_isSoftwareRecordingActive) {
|
|
1428
1447
|
resolve([NSNull null]);
|
|
1429
1448
|
return;
|
|
1430
1449
|
}
|
|
1431
1450
|
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1451
|
+
self->_isSoftwareRecordingActive = NO;
|
|
1452
|
+
if (self->_softwareRecordingTimerSource) {
|
|
1453
|
+
dispatch_source_cancel(self->_softwareRecordingTimerSource);
|
|
1454
|
+
self->_softwareRecordingTimerSource = nil;
|
|
1455
|
+
}
|
|
1436
1456
|
|
|
1437
|
-
[
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1457
|
+
[self->_softwareWriterInput markAsFinished];
|
|
1458
|
+
NSString *filePath = self->_softwareRecordingFilePath;
|
|
1459
|
+
NSString *thumbPath = self->_softwareRecordingThumbnailPath;
|
|
1460
|
+
NSTimeInterval duration = [[NSDate date] timeIntervalSince1970] - self->_softwareRecordingStartTime;
|
|
1461
|
+
long long timestamp = self->_softwareRecordingTimestamp > 0 ? self->_softwareRecordingTimestamp : (long long)(self->_softwareRecordingStartTime * 1000.0);
|
|
1462
|
+
NSInteger vidWidth = self->_softwareVideoWidth > 0 ? self->_softwareVideoWidth : 720;
|
|
1463
|
+
NSInteger vidHeight = self->_softwareVideoHeight > 0 ? self->_softwareVideoHeight : 1280;
|
|
1442
1464
|
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
if (videoTracks.count > 0) {
|
|
1449
|
-
naturalSize = videoTracks.firstObject.naturalSize;
|
|
1450
|
-
}
|
|
1465
|
+
[self->_softwareAssetWriter finishWritingWithCompletionHandler:^{
|
|
1466
|
+
self->_softwareAssetWriter = nil;
|
|
1467
|
+
self->_softwareWriterInput = nil;
|
|
1468
|
+
self->_softwarePixelBufferAdaptor = nil;
|
|
1469
|
+
self->_softwareRecordingThumbnailPath = nil;
|
|
1451
1470
|
|
|
1452
1471
|
unsigned long long fileSize = 0;
|
|
1453
1472
|
NSDictionary *attrs = [[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:nil];
|
|
@@ -1455,24 +1474,71 @@ RCT_EXPORT_METHOD(stopVideoRecording:(RCTPromiseResolveBlock)resolve
|
|
|
1455
1474
|
fileSize = [attrs fileSize];
|
|
1456
1475
|
}
|
|
1457
1476
|
|
|
1458
|
-
|
|
1459
|
-
@"uri":
|
|
1477
|
+
NSMutableDictionary *result = [NSMutableDictionary dictionaryWithDictionary:@{
|
|
1478
|
+
@"uri": [NSURL fileURLWithPath:filePath].absoluteString,
|
|
1460
1479
|
@"format": @"mp4",
|
|
1461
|
-
@"durationMs": @(
|
|
1462
|
-
@"hasAudio": @(
|
|
1463
|
-
@"width": @(
|
|
1464
|
-
@"height": @(
|
|
1480
|
+
@"durationMs": @(MAX(500.0, duration * 1000.0)),
|
|
1481
|
+
@"hasAudio": @(NO),
|
|
1482
|
+
@"width": @(vidWidth),
|
|
1483
|
+
@"height": @(vidHeight),
|
|
1465
1484
|
@"sizeBytes": @(fileSize),
|
|
1466
1485
|
@"timestamp": @(timestamp)
|
|
1467
|
-
};
|
|
1486
|
+
}];
|
|
1487
|
+
|
|
1488
|
+
if (thumbPath && [[NSFileManager defaultManager] fileExistsAtPath:thumbPath]) {
|
|
1489
|
+
result[@"thumbnailUri"] = [NSURL fileURLWithPath:thumbPath].absoluteString;
|
|
1490
|
+
}
|
|
1491
|
+
|
|
1468
1492
|
resolve(result);
|
|
1469
1493
|
}];
|
|
1470
1494
|
}
|
|
1471
1495
|
|
|
1472
1496
|
RCT_EXPORT_METHOD(isRecording:(RCTPromiseResolveBlock)resolve
|
|
1473
1497
|
reject:(RCTPromiseRejectBlock)reject) {
|
|
1474
|
-
|
|
1475
|
-
|
|
1498
|
+
resolve(@(self->_isSoftwareRecordingActive));
|
|
1499
|
+
}
|
|
1500
|
+
|
|
1501
|
+
RCT_EXPORT_METHOD(playVideo:(NSString *)videoUri
|
|
1502
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
1503
|
+
reject:(RCTPromiseRejectBlock)reject) {
|
|
1504
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
1505
|
+
@try {
|
|
1506
|
+
if (!videoUri || videoUri.length == 0) {
|
|
1507
|
+
reject(@"PLAY_ERROR", @"Invalid video URI", nil);
|
|
1508
|
+
return;
|
|
1509
|
+
}
|
|
1510
|
+
NSURL *url = [NSURL URLWithString:videoUri];
|
|
1511
|
+
if (!url || !url.scheme) {
|
|
1512
|
+
url = [NSURL fileURLWithPath:videoUri];
|
|
1513
|
+
}
|
|
1514
|
+
|
|
1515
|
+
AVPlayer *player = [AVPlayer playerWithURL:url];
|
|
1516
|
+
AVPlayerViewController *playerController = [[AVPlayerViewController alloc] init];
|
|
1517
|
+
playerController.player = player;
|
|
1518
|
+
playerController.showsPlaybackControls = YES;
|
|
1519
|
+
playerController.modalPresentationStyle = UIModalPresentationFullScreen;
|
|
1520
|
+
|
|
1521
|
+
UIWindow *keyWindow = [self findActiveKeyWindow];
|
|
1522
|
+
UIViewController *rootVC = keyWindow.rootViewController;
|
|
1523
|
+
if (!rootVC) {
|
|
1524
|
+
rootVC = [UIApplication sharedApplication].delegate.window.rootViewController;
|
|
1525
|
+
}
|
|
1526
|
+
while (rootVC.presentedViewController) {
|
|
1527
|
+
rootVC = rootVC.presentedViewController;
|
|
1528
|
+
}
|
|
1529
|
+
|
|
1530
|
+
if (rootVC) {
|
|
1531
|
+
[rootVC presentViewController:playerController animated:YES completion:^{
|
|
1532
|
+
[player play];
|
|
1533
|
+
resolve(@(YES));
|
|
1534
|
+
}];
|
|
1535
|
+
} else {
|
|
1536
|
+
reject(@"PLAY_ERROR", @"Unable to find view controller to present video player", nil);
|
|
1537
|
+
}
|
|
1538
|
+
} @catch (NSException *ex) {
|
|
1539
|
+
reject(@"PLAY_ERROR", ex.reason, nil);
|
|
1540
|
+
}
|
|
1541
|
+
});
|
|
1476
1542
|
}
|
|
1477
1543
|
|
|
1478
1544
|
RCT_EXPORT_METHOD(convertToGif:(NSString *)videoUri
|
|
@@ -1597,6 +1663,9 @@ RCT_EXPORT_METHOD(getCapturedMedia:(RCTPromiseResolveBlock)resolve
|
|
|
1597
1663
|
NSMutableArray *mediaItems = [NSMutableArray array];
|
|
1598
1664
|
|
|
1599
1665
|
for (NSString *file in (files ?: @[])) {
|
|
1666
|
+
// Skip standalone thumbnail files
|
|
1667
|
+
if ([file hasPrefix:@"thumb_"]) continue;
|
|
1668
|
+
|
|
1600
1669
|
NSString *fullPath = [dir stringByAppendingPathComponent:file];
|
|
1601
1670
|
NSDictionary *attrs = [[NSFileManager defaultManager] attributesOfItemAtPath:fullPath error:nil];
|
|
1602
1671
|
if (!attrs) continue;
|
|
@@ -1613,7 +1682,7 @@ RCT_EXPORT_METHOD(getCapturedMedia:(RCTPromiseResolveBlock)resolve
|
|
|
1613
1682
|
NSDate *modDate = [attrs fileModificationDate];
|
|
1614
1683
|
long long timestamp = (long long)([modDate timeIntervalSince1970] * 1000.0);
|
|
1615
1684
|
|
|
1616
|
-
[
|
|
1685
|
+
NSMutableDictionary *item = [NSMutableDictionary dictionaryWithDictionary:@{
|
|
1617
1686
|
@"id": file,
|
|
1618
1687
|
@"type": type,
|
|
1619
1688
|
@"format": ext,
|
|
@@ -1622,6 +1691,41 @@ RCT_EXPORT_METHOD(getCapturedMedia:(RCTPromiseResolveBlock)resolve
|
|
|
1622
1691
|
@"sizeBytes": @(sizeBytes),
|
|
1623
1692
|
@"timestamp": @(timestamp)
|
|
1624
1693
|
}];
|
|
1694
|
+
|
|
1695
|
+
if ([type isEqualToString:@"video"]) {
|
|
1696
|
+
// Check if matching thumbnail exists
|
|
1697
|
+
NSString *nameWithoutExt = [file stringByDeletingPathExtension];
|
|
1698
|
+
NSString *timestampSuffix = [nameWithoutExt stringByReplacingOccurrencesOfString:@"video_" withString:@""];
|
|
1699
|
+
NSString *thumbFile = [NSString stringWithFormat:@"thumb_%@.jpg", timestampSuffix];
|
|
1700
|
+
NSString *thumbFullPath = [dir stringByAppendingPathComponent:thumbFile];
|
|
1701
|
+
if ([[NSFileManager defaultManager] fileExistsAtPath:thumbFullPath]) {
|
|
1702
|
+
item[@"thumbnailUri"] = [NSURL fileURLWithPath:thumbFullPath].absoluteString;
|
|
1703
|
+
} else {
|
|
1704
|
+
@try {
|
|
1705
|
+
NSURL *vidUrl = [NSURL fileURLWithPath:fullPath];
|
|
1706
|
+
AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:vidUrl options:nil];
|
|
1707
|
+
AVAssetImageGenerator *gen = [[AVAssetImageGenerator alloc] initWithAsset:asset];
|
|
1708
|
+
gen.appliesPreferredTrackTransform = YES;
|
|
1709
|
+
gen.requestedTimeToleranceBefore = kCMTimePositiveInfinity;
|
|
1710
|
+
gen.requestedTimeToleranceAfter = kCMTimePositiveInfinity;
|
|
1711
|
+
gen.maximumSize = CGSizeMake(720, 720);
|
|
1712
|
+
CMTime time = kCMTimeZero;
|
|
1713
|
+
NSError *err = nil;
|
|
1714
|
+
CGImageRef imgRef = [gen copyCGImageAtTime:time actualTime:NULL error:&err];
|
|
1715
|
+
if (imgRef) {
|
|
1716
|
+
UIImage *thumbImg = [UIImage imageWithCGImage:imgRef];
|
|
1717
|
+
CGImageRelease(imgRef);
|
|
1718
|
+
NSData *tData = UIImageJPEGRepresentation(thumbImg, 0.85);
|
|
1719
|
+
if (tData) {
|
|
1720
|
+
[tData writeToFile:thumbFullPath atomically:YES];
|
|
1721
|
+
item[@"thumbnailUri"] = [NSURL fileURLWithPath:thumbFullPath].absoluteString;
|
|
1722
|
+
}
|
|
1723
|
+
}
|
|
1724
|
+
} @catch (NSException *e) {}
|
|
1725
|
+
}
|
|
1726
|
+
}
|
|
1727
|
+
|
|
1728
|
+
[mediaItems addObject:item];
|
|
1625
1729
|
}
|
|
1626
1730
|
|
|
1627
1731
|
[mediaItems sortUsingComparator:^NSComparisonResult(id obj1, id obj2) {
|
|
@@ -1643,6 +1747,19 @@ RCT_EXPORT_METHOD(deleteCapturedMedia:(NSString *)uri
|
|
|
1643
1747
|
NSString *path = url ? url.path : uri;
|
|
1644
1748
|
if ([[NSFileManager defaultManager] fileExistsAtPath:path]) {
|
|
1645
1749
|
[[NSFileManager defaultManager] removeItemAtPath:path error:nil];
|
|
1750
|
+
|
|
1751
|
+
// Also remove any related thumbnail
|
|
1752
|
+
NSString *filename = [path lastPathComponent];
|
|
1753
|
+
if ([filename hasPrefix:@"video_"]) {
|
|
1754
|
+
NSString *nameWithoutExt = [filename stringByDeletingPathExtension];
|
|
1755
|
+
NSString *timestampSuffix = [nameWithoutExt stringByReplacingOccurrencesOfString:@"video_" withString:@""];
|
|
1756
|
+
NSString *thumbFile = [NSString stringWithFormat:@"thumb_%@.jpg", timestampSuffix];
|
|
1757
|
+
NSString *thumbPath = [[path stringByDeletingLastPathComponent] stringByAppendingPathComponent:thumbFile];
|
|
1758
|
+
if ([[NSFileManager defaultManager] fileExistsAtPath:thumbPath]) {
|
|
1759
|
+
[[NSFileManager defaultManager] removeItemAtPath:thumbPath error:nil];
|
|
1760
|
+
}
|
|
1761
|
+
}
|
|
1762
|
+
|
|
1646
1763
|
resolve(@(YES));
|
|
1647
1764
|
} else {
|
|
1648
1765
|
resolve(@(NO));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-inapp-inspector",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.20",
|
|
4
4
|
"description": "The zero-config, all-in-one in-app debugger for React Native & Expo. Inspect Network (fetch/axios), Console logs, Stack Traces, Redux State, Firebase Analytics, and JS Bundle size directly on device.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -97,7 +97,7 @@
|
|
|
97
97
|
},
|
|
98
98
|
"files": [
|
|
99
99
|
"dist",
|
|
100
|
-
"src",
|
|
100
|
+
"src/native",
|
|
101
101
|
"bin",
|
|
102
102
|
"metro.js",
|
|
103
103
|
"metro.d.ts",
|
|
@@ -117,7 +117,7 @@
|
|
|
117
117
|
"scripts": {
|
|
118
118
|
"clean": "rm -rf dist",
|
|
119
119
|
"prebuild": "node scripts/gen-version.js && node scripts/gen-telemetry.js",
|
|
120
|
-
"build": "tsc && tsc -p tsconfig.esm.json",
|
|
120
|
+
"build": "tsc && tsc -p tsconfig.esm.json && node scripts/minify-dist.js",
|
|
121
121
|
"clean-build": "npm run clean && npm run build",
|
|
122
122
|
"prepare": "npm run build",
|
|
123
123
|
"watch": "tsc -w",
|
|
@@ -186,12 +186,14 @@
|
|
|
186
186
|
"@types/react": "19.1.0",
|
|
187
187
|
"@types/react-native": "0.72.0",
|
|
188
188
|
"axios": "1.7.2",
|
|
189
|
+
"esbuild": "^0.28.2",
|
|
189
190
|
"prettier": "2.8.8",
|
|
190
191
|
"react": "19.1.0",
|
|
191
192
|
"react-native": "0.81.4",
|
|
192
193
|
"react-native-bundle-visualizer": "4.0.0",
|
|
193
194
|
"react-native-linear-gradient": "2.8.3",
|
|
194
195
|
"react-native-svg": "15.14.0",
|
|
196
|
+
"terser": "^5.51.2",
|
|
195
197
|
"typescript": "5.8.3"
|
|
196
198
|
},
|
|
197
199
|
"dependencies": {
|
|
@@ -13,7 +13,7 @@ Pod::Spec.new do |s|
|
|
|
13
13
|
s.source = { :git => "https://github.com/vengatmacuser/react-native-inapp-inspector.git", :tag => "v#{s.version}" }
|
|
14
14
|
s.source_files = "ios/**/*.{h,m,mm,swift}"
|
|
15
15
|
s.requires_arc = true
|
|
16
|
-
s.frameworks = "AVFoundation", "ReplayKit", "CoreMedia", "CoreVideo", "ImageIO", "MobileCoreServices", "QuartzCore"
|
|
16
|
+
s.frameworks = "AVFoundation", "AVKit", "ReplayKit", "CoreMedia", "CoreVideo", "ImageIO", "MobileCoreServices", "QuartzCore"
|
|
17
17
|
|
|
18
18
|
# React Native New Architecture (TurboModules & Codegen) support
|
|
19
19
|
if respond_to?(:install_modules_dependencies, true)
|
|
@@ -468,6 +468,7 @@ export interface RecordingOptions {
|
|
|
468
468
|
|
|
469
469
|
export interface RecordingResult {
|
|
470
470
|
uri: string;
|
|
471
|
+
thumbnailUri?: string;
|
|
471
472
|
format: 'mp4' | 'gif';
|
|
472
473
|
durationMs: number;
|
|
473
474
|
hasAudio: boolean;
|
|
@@ -488,6 +489,7 @@ export interface CapturedMediaItem {
|
|
|
488
489
|
type: 'image' | 'video' | 'gif';
|
|
489
490
|
format: string;
|
|
490
491
|
uri: string;
|
|
492
|
+
thumbnailUri?: string;
|
|
491
493
|
filename: string;
|
|
492
494
|
sizeBytes: number;
|
|
493
495
|
timestamp: number;
|
|
@@ -561,6 +563,21 @@ export const isNativeRecordingActive = async (): Promise<boolean> => {
|
|
|
561
563
|
}
|
|
562
564
|
};
|
|
563
565
|
|
|
566
|
+
/**
|
|
567
|
+
* Plays a recorded video file using the native system media player.
|
|
568
|
+
*/
|
|
569
|
+
export const playNativeVideo = async (videoUri: string): Promise<boolean> => {
|
|
570
|
+
if (!NativeModule || !NativeModule.playVideo) {
|
|
571
|
+
return false;
|
|
572
|
+
}
|
|
573
|
+
try {
|
|
574
|
+
const result = await NativeModule.playVideo(videoUri);
|
|
575
|
+
return !!result;
|
|
576
|
+
} catch {
|
|
577
|
+
return false;
|
|
578
|
+
}
|
|
579
|
+
};
|
|
580
|
+
|
|
564
581
|
/**
|
|
565
582
|
* Converts a recorded MP4 video to an animated GIF.
|
|
566
583
|
*/
|
|
@@ -22,6 +22,7 @@ export interface Spec extends TurboModule {
|
|
|
22
22
|
stopVideoRecording(): Promise<Object>;
|
|
23
23
|
isRecording(): Promise<boolean>;
|
|
24
24
|
convertToGif(videoUri: string, options: Object): Promise<Object>;
|
|
25
|
+
playVideo(videoUri: string): Promise<boolean>;
|
|
25
26
|
getCapturedMedia(): Promise<string>;
|
|
26
27
|
deleteCapturedMedia(uri: string): Promise<boolean>;
|
|
27
28
|
clearAllCapturedMedia(): Promise<boolean>;
|