react-native-inapp-inspector 2.4.2 → 2.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/.gradle/8.9/checksums/checksums.lock +0 -0
- package/android/.gradle/8.9/dependencies-accessors/gc.properties +0 -0
- package/android/.gradle/8.9/executionHistory/executionHistory.lock +0 -0
- package/android/.gradle/8.9/fileChanges/last-build.bin +0 -0
- package/android/.gradle/8.9/fileHashes/fileHashes.lock +0 -0
- package/android/.gradle/8.9/gc.properties +0 -0
- package/android/.gradle/9.2.0/checksums/checksums.lock +0 -0
- package/android/.gradle/9.2.0/fileChanges/last-build.bin +0 -0
- package/android/.gradle/9.2.0/fileHashes/fileHashes.bin +0 -0
- package/android/.gradle/9.2.0/fileHashes/fileHashes.lock +0 -0
- package/android/.gradle/9.2.0/gc.properties +0 -0
- package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
- package/android/.gradle/buildOutputCleanup/cache.properties +2 -0
- package/android/.gradle/vcs-1/gc.properties +0 -0
- package/android/.settings/org.eclipse.buildship.core.prefs +13 -0
- package/android/src/main/java/com/inappinspector/NetworkInspectorModule.kt +523 -2
- package/dist/commonjs/capture.d.ts +2 -0
- package/dist/commonjs/capture.js +1 -1
- package/dist/commonjs/components/AnalyticsDetail.js +23 -23
- package/dist/commonjs/components/AnalyticsEventCard.js +1 -1
- package/dist/commonjs/components/AnalyticsGraph.js +44 -44
- package/dist/commonjs/components/AnimatedBrandOwl.js +32 -32
- package/dist/commonjs/components/AppHeaderLogo.js +6 -6
- package/dist/commonjs/components/BrandCircleIcon.js +28 -28
- package/dist/commonjs/components/BrandSquareIcon.js +33 -33
- package/dist/commonjs/components/ConsoleLogCard.js +1 -1
- package/dist/commonjs/components/Inspector/AnalyticsTab.js +2 -2
- package/dist/commonjs/components/Inspector/ConfirmationModal.js +23 -25
- package/dist/commonjs/components/Inspector/ConsoleTab.js +5 -5
- package/dist/commonjs/components/Inspector/CrashTab.js +44 -11
- package/dist/commonjs/components/Inspector/DeviceInfoTab.js +1 -1
- package/dist/commonjs/components/Inspector/FabLauncher.js +30 -25
- package/dist/commonjs/components/Inspector/FloatingCaptureWidget.d.ts +3 -0
- package/dist/commonjs/components/Inspector/FloatingCaptureWidget.js +54 -0
- package/dist/commonjs/components/Inspector/GlobalCrashScreenModal.d.ts +11 -0
- package/dist/commonjs/components/Inspector/GlobalCrashScreenModal.js +234 -0
- package/dist/commonjs/components/Inspector/InspectorHeader.js +137 -127
- package/dist/commonjs/components/Inspector/LanguageSelectorModal.d.ts +1 -1
- package/dist/commonjs/components/Inspector/LanguageSelectorModal.js +114 -32
- package/dist/commonjs/components/Inspector/MainScreen.js +26 -19
- package/dist/commonjs/components/Inspector/MediaGalleryTab.js +38 -35
- package/dist/commonjs/components/Inspector/MediaPreviewModal.d.ts +36 -0
- package/dist/commonjs/components/Inspector/MediaPreviewModal.js +345 -123
- package/dist/commonjs/components/Inspector/NetworkTab.js +14 -14
- package/dist/commonjs/components/Inspector/PushCard.js +1 -1
- package/dist/commonjs/components/Inspector/PushDetail.js +9 -9
- package/dist/commonjs/components/Inspector/PushTab.js +3 -3
- package/dist/commonjs/components/Inspector/ReduxTab.js +9 -7
- package/dist/commonjs/components/Inspector/SecondaryTelemetryStrip.d.ts +2 -0
- package/dist/commonjs/components/Inspector/SecondaryTelemetryStrip.js +43 -0
- package/dist/commonjs/components/Inspector/SettingsPanel.js +102 -73
- package/dist/commonjs/components/Inspector/SocketCard.js +1 -1
- package/dist/commonjs/components/Inspector/SocketDetail.js +73 -63
- package/dist/commonjs/components/Inspector/SocketTab.js +4 -4
- package/dist/commonjs/components/Inspector/StorageTab.js +10 -10
- package/dist/commonjs/components/Inspector/SupportModal.js +2 -2
- package/dist/commonjs/components/Inspector/SupportPage.js +1 -1
- package/dist/commonjs/components/JsonViewer.js +47 -45
- package/dist/commonjs/components/LogCard.js +22 -20
- package/dist/commonjs/components/ModuleErrorBoundary.js +5 -5
- package/dist/commonjs/components/NetworkIcons.d.ts +27 -0
- package/dist/commonjs/components/NetworkIcons.js +103 -5
- package/dist/commonjs/constants/telemetryConfig.d.ts +3 -3
- package/dist/commonjs/constants/telemetryConfig.js +1 -1
- package/dist/commonjs/constants/version.d.ts +1 -1
- package/dist/commonjs/constants/version.js +1 -1
- package/dist/commonjs/crash.d.ts +1 -1
- package/dist/commonjs/crash.js +1 -1
- package/dist/commonjs/customHooks/crashHandler.d.ts +2 -1
- package/dist/commonjs/customHooks/crashHandler.js +7 -7
- package/dist/commonjs/editor.d.ts +13 -0
- package/dist/commonjs/editor.js +1 -0
- package/dist/commonjs/helpers/index.d.ts +1 -0
- package/dist/commonjs/helpers/index.js +1 -1
- package/dist/commonjs/helpers/settingsStore.js +1 -1
- package/dist/commonjs/helpers/telemetry.js +1 -1
- package/dist/commonjs/i18n/index.js +1 -1
- package/dist/commonjs/i18n/locales/ar.json +1 -1
- package/dist/commonjs/i18n/locales/bn.json +1 -1
- package/dist/commonjs/i18n/locales/de.json +1 -1
- package/dist/commonjs/i18n/locales/en.json +1 -1
- package/dist/commonjs/i18n/locales/es.json +1 -1
- package/dist/commonjs/i18n/locales/fr.json +1 -1
- package/dist/commonjs/i18n/locales/gu.json +1 -1
- package/dist/commonjs/i18n/locales/hi.json +1 -1
- package/dist/commonjs/i18n/locales/id.json +1 -1
- package/dist/commonjs/i18n/locales/it.json +1 -1
- package/dist/commonjs/i18n/locales/ja.json +1 -1
- package/dist/commonjs/i18n/locales/kn.json +1 -1
- package/dist/commonjs/i18n/locales/ko.json +1 -1
- package/dist/commonjs/i18n/locales/ml.json +1 -1
- package/dist/commonjs/i18n/locales/mr.json +1 -1
- package/dist/commonjs/i18n/locales/nl.json +1 -1
- package/dist/commonjs/i18n/locales/pa.json +1 -1
- package/dist/commonjs/i18n/locales/pl.json +1 -1
- package/dist/commonjs/i18n/locales/pt.json +1 -1
- package/dist/commonjs/i18n/locales/ru.json +1 -1
- package/dist/commonjs/i18n/locales/ta.json +1 -1
- package/dist/commonjs/i18n/locales/te.json +1 -1
- package/dist/commonjs/i18n/locales/tr.json +1 -1
- package/dist/commonjs/i18n/locales/vi.json +1 -1
- package/dist/commonjs/i18n/locales/zh.json +1 -1
- package/dist/commonjs/index.d.ts +4 -1
- package/dist/commonjs/index.js +3 -3
- package/dist/commonjs/native/NativeInspector.d.ts +3 -0
- package/dist/commonjs/native/NativeInspector.js +1 -1
- package/dist/commonjs/native/NativeNetworkInspector.d.ts +4 -0
- package/dist/commonjs/styles/AppColors.d.ts +42 -2
- package/dist/commonjs/styles/AppColors.js +1 -1
- package/dist/commonjs/styles/common.js +1 -1
- package/dist/commonjs/styles/index.d.ts +7 -0
- package/dist/commonjs/styles/index.js +1 -1
- package/dist/commonjs/types/editor.d.ts +96 -0
- package/dist/commonjs/types/editor.js +1 -0
- package/dist/commonjs/types/interfaces.d.ts +21 -0
- package/dist/esm/capture.d.ts +2 -0
- package/dist/esm/capture.js +1 -1
- package/dist/esm/components/AnalyticsDetail.js +31 -31
- package/dist/esm/components/AnalyticsEventCard.js +1 -1
- package/dist/esm/components/AnalyticsGraph.js +74 -74
- package/dist/esm/components/AnimatedBrandOwl.js +114 -114
- package/dist/esm/components/AppHeaderLogo.js +7 -7
- package/dist/esm/components/BrandCircleIcon.js +70 -70
- package/dist/esm/components/BrandSquareIcon.js +61 -61
- package/dist/esm/components/ConsoleLogCard.js +1 -1
- package/dist/esm/components/Inspector/AnalyticsTab.js +14 -14
- package/dist/esm/components/Inspector/ConfirmationModal.js +23 -25
- package/dist/esm/components/Inspector/ConsoleTab.js +17 -17
- package/dist/esm/components/Inspector/CrashTab.js +202 -169
- package/dist/esm/components/Inspector/DeviceInfoTab.js +75 -75
- package/dist/esm/components/Inspector/FabLauncher.js +56 -51
- package/dist/esm/components/Inspector/FloatingCaptureWidget.d.ts +3 -0
- package/dist/esm/components/Inspector/FloatingCaptureWidget.js +54 -0
- package/dist/esm/components/Inspector/GlobalCrashScreenModal.d.ts +11 -0
- package/dist/esm/components/Inspector/GlobalCrashScreenModal.js +234 -0
- package/dist/esm/components/Inspector/InspectorHeader.js +162 -152
- package/dist/esm/components/Inspector/LanguageSelectorModal.d.ts +1 -1
- package/dist/esm/components/Inspector/LanguageSelectorModal.js +140 -58
- package/dist/esm/components/Inspector/MainScreen.js +61 -54
- package/dist/esm/components/Inspector/MediaGalleryTab.js +55 -52
- package/dist/esm/components/Inspector/MediaPreviewModal.d.ts +36 -0
- package/dist/esm/components/Inspector/MediaPreviewModal.js +345 -123
- package/dist/esm/components/Inspector/NetworkTab.js +74 -74
- package/dist/esm/components/Inspector/PushCard.js +1 -1
- package/dist/esm/components/Inspector/PushDetail.js +18 -18
- package/dist/esm/components/Inspector/PushTab.js +1 -1
- package/dist/esm/components/Inspector/ReduxTab.js +18 -16
- package/dist/esm/components/Inspector/SecondaryTelemetryStrip.d.ts +2 -0
- package/dist/esm/components/Inspector/SecondaryTelemetryStrip.js +43 -0
- package/dist/esm/components/Inspector/SettingsPanel.js +224 -195
- package/dist/esm/components/Inspector/SocketCard.js +8 -8
- package/dist/esm/components/Inspector/SocketDetail.js +106 -96
- package/dist/esm/components/Inspector/SocketTab.js +18 -18
- package/dist/esm/components/Inspector/StorageTab.js +47 -47
- package/dist/esm/components/Inspector/SupportModal.js +64 -64
- package/dist/esm/components/Inspector/SupportPage.js +5 -5
- package/dist/esm/components/JsonViewer.js +51 -49
- package/dist/esm/components/LogCard.js +41 -39
- package/dist/esm/components/ModuleErrorBoundary.js +10 -10
- package/dist/esm/components/NetworkIcons.d.ts +27 -0
- package/dist/esm/components/NetworkIcons.js +101 -3
- package/dist/esm/constants/telemetryConfig.d.ts +3 -3
- package/dist/esm/constants/telemetryConfig.js +1 -1
- package/dist/esm/constants/version.d.ts +1 -1
- package/dist/esm/constants/version.js +1 -1
- package/dist/esm/crash.d.ts +1 -1
- package/dist/esm/crash.js +1 -1
- package/dist/esm/customHooks/crashHandler.d.ts +2 -1
- package/dist/esm/customHooks/crashHandler.js +7 -7
- package/dist/esm/editor.d.ts +13 -0
- package/dist/esm/editor.js +1 -0
- package/dist/esm/helpers/index.d.ts +1 -0
- package/dist/esm/helpers/index.js +4 -4
- package/dist/esm/helpers/settingsStore.js +1 -1
- package/dist/esm/helpers/telemetry.js +1 -1
- package/dist/esm/i18n/index.js +1 -1
- package/dist/esm/i18n/locales/ar.json +1 -1
- package/dist/esm/i18n/locales/bn.json +1 -1
- package/dist/esm/i18n/locales/de.json +1 -1
- package/dist/esm/i18n/locales/en.json +1 -1
- package/dist/esm/i18n/locales/es.json +1 -1
- package/dist/esm/i18n/locales/fr.json +1 -1
- package/dist/esm/i18n/locales/gu.json +1 -1
- package/dist/esm/i18n/locales/hi.json +1 -1
- package/dist/esm/i18n/locales/id.json +1 -1
- package/dist/esm/i18n/locales/it.json +1 -1
- package/dist/esm/i18n/locales/ja.json +1 -1
- package/dist/esm/i18n/locales/kn.json +1 -1
- package/dist/esm/i18n/locales/ko.json +1 -1
- package/dist/esm/i18n/locales/ml.json +1 -1
- package/dist/esm/i18n/locales/mr.json +1 -1
- package/dist/esm/i18n/locales/nl.json +1 -1
- package/dist/esm/i18n/locales/pa.json +1 -1
- package/dist/esm/i18n/locales/pl.json +1 -1
- package/dist/esm/i18n/locales/pt.json +1 -1
- package/dist/esm/i18n/locales/ru.json +1 -1
- package/dist/esm/i18n/locales/ta.json +1 -1
- package/dist/esm/i18n/locales/te.json +1 -1
- package/dist/esm/i18n/locales/tr.json +1 -1
- package/dist/esm/i18n/locales/vi.json +1 -1
- package/dist/esm/i18n/locales/zh.json +1 -1
- package/dist/esm/index.d.ts +4 -1
- package/dist/esm/index.js +5 -5
- package/dist/esm/native/NativeInspector.d.ts +3 -0
- package/dist/esm/native/NativeInspector.js +1 -1
- package/dist/esm/native/NativeNetworkInspector.d.ts +4 -0
- package/dist/esm/styles/AppColors.d.ts +42 -2
- package/dist/esm/styles/AppColors.js +1 -1
- package/dist/esm/styles/common.js +1 -1
- package/dist/esm/styles/index.d.ts +7 -0
- package/dist/esm/styles/index.js +1 -1
- package/dist/esm/types/editor.d.ts +96 -0
- package/dist/esm/types/editor.js +1 -0
- package/dist/esm/types/interfaces.d.ts +21 -0
- package/editor.d.ts +1 -0
- package/editor.js +1 -0
- package/ios/NetworkInspectorModule.mm +429 -0
- package/package.json +10 -1
- package/react-native-inapp-inspector.podspec +1 -1
- package/src/native/NativeInspector.ts +57 -4
- package/src/native/NativeNetworkInspector.ts +4 -0
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
#import <ReplayKit/ReplayKit.h>
|
|
7
7
|
#import <AVFoundation/AVFoundation.h>
|
|
8
8
|
#import <AVKit/AVKit.h>
|
|
9
|
+
#import <CoreImage/CoreImage.h>
|
|
9
10
|
#import <ImageIO/ImageIO.h>
|
|
10
11
|
#import <MobileCoreServices/MobileCoreServices.h>
|
|
11
12
|
|
|
@@ -1911,6 +1912,434 @@ RCT_EXPORT_METHOD(clearAllCapturedMedia:(RCTPromiseResolveBlock)resolve
|
|
|
1911
1912
|
});
|
|
1912
1913
|
}
|
|
1913
1914
|
|
|
1915
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
1916
|
+
// 100% Native Media Editor: Photo Editing (CoreImage + ImageIO)
|
|
1917
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
1918
|
+
|
|
1919
|
+
RCT_EXPORT_METHOD(editPhoto:(NSDictionary *)options
|
|
1920
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
1921
|
+
reject:(RCTPromiseRejectBlock)reject) {
|
|
1922
|
+
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
|
+
}
|
|
1941
|
+
|
|
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
|
+
}
|
|
1951
|
+
|
|
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
|
+
}
|
|
1977
|
+
|
|
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;
|
|
1993
|
+
}
|
|
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];
|
|
2000
|
+
}
|
|
2001
|
+
}
|
|
2002
|
+
|
|
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;
|
|
2017
|
+
}
|
|
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;
|
|
2029
|
+
}
|
|
2030
|
+
|
|
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;
|
|
2038
|
+
}
|
|
2039
|
+
|
|
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;
|
|
2046
|
+
}
|
|
2047
|
+
}
|
|
2048
|
+
|
|
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;
|
|
2064
|
+
}
|
|
2065
|
+
}
|
|
2066
|
+
|
|
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
|
+
}
|
|
2074
|
+
|
|
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;
|
|
2099
|
+
}
|
|
2100
|
+
CGContextSetFillColorWithColor(ctx, [UIColor blackColor].CGColor);
|
|
2101
|
+
CGContextFillRect(ctx, CGRectMake(x, y, w, h));
|
|
2102
|
+
}
|
|
2103
|
+
}
|
|
2104
|
+
|
|
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;
|
|
2117
|
+
}
|
|
2118
|
+
CGContextSetStrokeColorWithColor(ctx, [UIColor redColor].CGColor);
|
|
2119
|
+
CGContextSetLineWidth(ctx, 4.0);
|
|
2120
|
+
CGContextStrokeRect(ctx, CGRectMake(x, y, w, h));
|
|
2121
|
+
}
|
|
2122
|
+
}
|
|
2123
|
+
|
|
2124
|
+
resultImage = UIGraphicsGetImageFromCurrentImageContext();
|
|
2125
|
+
UIGraphicsEndImageContext();
|
|
2126
|
+
}
|
|
2127
|
+
|
|
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";
|
|
2133
|
+
|
|
2134
|
+
if ([format isEqualToString:@"png"]) {
|
|
2135
|
+
imageData = UIImagePNGRepresentation(resultImage);
|
|
2136
|
+
ext = @"png";
|
|
2137
|
+
mime = @"image/png";
|
|
2138
|
+
} else {
|
|
2139
|
+
imageData = UIImageJPEGRepresentation(resultImage, quality);
|
|
2140
|
+
}
|
|
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
|
+
}
|
|
2159
|
+
});
|
|
2160
|
+
}
|
|
2161
|
+
|
|
2162
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
2163
|
+
// 100% Native Media Editor: Video Trimming (AVFoundation)
|
|
2164
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
2165
|
+
|
|
2166
|
+
RCT_EXPORT_METHOD(trimVideo:(NSDictionary *)options
|
|
2167
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
2168
|
+
reject:(RCTPromiseRejectBlock)reject) {
|
|
2169
|
+
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
|
2170
|
+
@try {
|
|
2171
|
+
NSString *rawUri = options[@"uri"];
|
|
2172
|
+
if (!rawUri || rawUri.length == 0) {
|
|
2173
|
+
reject(@"INVALID_URI", @"Video URI is missing", nil);
|
|
2174
|
+
return;
|
|
2175
|
+
}
|
|
2176
|
+
|
|
2177
|
+
NSURL *sourceUrl = [NSURL URLWithString:rawUri];
|
|
2178
|
+
if (!sourceUrl.scheme) {
|
|
2179
|
+
sourceUrl = [NSURL fileURLWithPath:rawUri];
|
|
2180
|
+
}
|
|
2181
|
+
|
|
2182
|
+
AVURLAsset *asset = [AVURLAsset URLAssetWithURL:sourceUrl options:nil];
|
|
2183
|
+
double startMs = [options[@"startTimeMs"] doubleValue];
|
|
2184
|
+
double endMs = [options[@"endTimeMs"] doubleValue];
|
|
2185
|
+
BOOL mute = [options[@"mute"] boolValue] || [options[@"muteAudio"] boolValue];
|
|
2186
|
+
|
|
2187
|
+
AVAssetTrack *videoTrack = [[asset tracksWithMediaType:AVMediaTypeVideo] firstObject];
|
|
2188
|
+
if (!videoTrack) {
|
|
2189
|
+
reject(@"NO_VIDEO_TRACK", @"Source video has no valid video track", nil);
|
|
2190
|
+
return;
|
|
2191
|
+
}
|
|
2192
|
+
|
|
2193
|
+
double trackDurationSec = CMTimeGetSeconds(videoTrack.timeRange.duration);
|
|
2194
|
+
if (isnan(trackDurationSec) || trackDurationSec <= 0) {
|
|
2195
|
+
trackDurationSec = CMTimeGetSeconds(asset.duration);
|
|
2196
|
+
}
|
|
2197
|
+
double trackDurationMs = trackDurationSec * 1000.0;
|
|
2198
|
+
if (endMs > trackDurationMs || endMs <= 0) {
|
|
2199
|
+
endMs = trackDurationMs;
|
|
2200
|
+
}
|
|
2201
|
+
if (startMs >= endMs) {
|
|
2202
|
+
startMs = 0;
|
|
2203
|
+
}
|
|
2204
|
+
|
|
2205
|
+
AVMutableComposition *composition = [AVMutableComposition composition];
|
|
2206
|
+
AVMutableCompositionTrack *compVideoTrack = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
|
|
2207
|
+
|
|
2208
|
+
CMTime startTime = CMTimeMakeWithSeconds(startMs / 1000.0, 600);
|
|
2209
|
+
CMTime durationTime = CMTimeMakeWithSeconds((endMs - startMs) / 1000.0, 600);
|
|
2210
|
+
CMTimeRange timeRange = CMTimeRangeMake(startTime, durationTime);
|
|
2211
|
+
|
|
2212
|
+
NSError *error = nil;
|
|
2213
|
+
[compVideoTrack insertTimeRange:timeRange ofTrack:videoTrack atTime:kCMTimeZero error:&error];
|
|
2214
|
+
compVideoTrack.preferredTransform = videoTrack.preferredTransform;
|
|
2215
|
+
|
|
2216
|
+
if (!mute) {
|
|
2217
|
+
AVAssetTrack *audioTrack = [[asset tracksWithMediaType:AVMediaTypeAudio] firstObject];
|
|
2218
|
+
if (audioTrack) {
|
|
2219
|
+
AVMutableCompositionTrack *compAudioTrack = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
|
|
2220
|
+
CMTimeRange audioTimeRange = timeRange;
|
|
2221
|
+
double audioDurationSec = CMTimeGetSeconds(audioTrack.timeRange.duration);
|
|
2222
|
+
if (!isnan(audioDurationSec) && audioDurationSec > 0) {
|
|
2223
|
+
double audioDurationMs = audioDurationSec * 1000.0;
|
|
2224
|
+
if (endMs > audioDurationMs) {
|
|
2225
|
+
audioTimeRange = CMTimeRangeMake(startTime, CMTimeMakeWithSeconds((audioDurationMs - startMs) / 1000.0, 600));
|
|
2226
|
+
}
|
|
2227
|
+
}
|
|
2228
|
+
[compAudioTrack insertTimeRange:audioTimeRange ofTrack:audioTrack atTime:kCMTimeZero error:nil];
|
|
2229
|
+
}
|
|
2230
|
+
}
|
|
2231
|
+
|
|
2232
|
+
NSString *preset = AVAssetExportPresetHighestQuality;
|
|
2233
|
+
NSString *quality = options[@"quality"];
|
|
2234
|
+
if ([quality isEqualToString:@"medium"]) preset = AVAssetExportPreset1280x720;
|
|
2235
|
+
else if ([quality isEqualToString:@"low"]) preset = AVAssetExportPreset640x480;
|
|
2236
|
+
|
|
2237
|
+
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]]];
|
|
2241
|
+
NSString *outPath = [[self getCapturesDirectory] stringByAppendingPathComponent:fileName];
|
|
2242
|
+
NSURL *outUrl = [NSURL fileURLWithPath:outPath];
|
|
2243
|
+
|
|
2244
|
+
exportSession.outputURL = outUrl;
|
|
2245
|
+
exportSession.outputFileType = AVFileTypeMPEG4;
|
|
2246
|
+
exportSession.shouldOptimizeForNetworkUse = YES;
|
|
2247
|
+
|
|
2248
|
+
[exportSession exportAsynchronouslyWithCompletionHandler:^{
|
|
2249
|
+
if (exportSession.status == AVAssetExportSessionStatusCompleted) {
|
|
2250
|
+
NSDictionary *attrs = [[NSFileManager defaultManager] attributesOfItemAtPath:outPath error:nil];
|
|
2251
|
+
CGSize natSize = CGSizeApplyAffineTransform(videoTrack.naturalSize, videoTrack.preferredTransform);
|
|
2252
|
+
resolve(@{
|
|
2253
|
+
@"uri": outUrl.absoluteString,
|
|
2254
|
+
@"durationMs": @(endMs - startMs),
|
|
2255
|
+
@"size": @([attrs fileSize]),
|
|
2256
|
+
@"width": @(fabs(natSize.width)),
|
|
2257
|
+
@"height": @(fabs(natSize.height)),
|
|
2258
|
+
@"format": @"mp4",
|
|
2259
|
+
});
|
|
2260
|
+
} else {
|
|
2261
|
+
reject(@"EXPORT_FAILED", exportSession.error.localizedDescription ?: @"Video export failed", exportSession.error);
|
|
2262
|
+
}
|
|
2263
|
+
}];
|
|
2264
|
+
} @catch (NSException *ex) {
|
|
2265
|
+
reject(@"TRIM_FAILED", ex.reason ?: @"Video trim failed", nil);
|
|
2266
|
+
}
|
|
2267
|
+
});
|
|
2268
|
+
}
|
|
2269
|
+
|
|
2270
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
2271
|
+
// 100% Native Media Editor: Filmstrip Thumbnail Generator (AVAssetImageGenerator)
|
|
2272
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
2273
|
+
|
|
2274
|
+
RCT_EXPORT_METHOD(generateFilmstrip:(NSDictionary *)options
|
|
2275
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
2276
|
+
reject:(RCTPromiseRejectBlock)reject) {
|
|
2277
|
+
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
|
2278
|
+
@try {
|
|
2279
|
+
NSString *rawUri = options[@"uri"];
|
|
2280
|
+
if (!rawUri || rawUri.length == 0) {
|
|
2281
|
+
reject(@"INVALID_URI", @"Video URI is missing", nil);
|
|
2282
|
+
return;
|
|
2283
|
+
}
|
|
2284
|
+
|
|
2285
|
+
NSURL *sourceUrl = [NSURL URLWithString:rawUri];
|
|
2286
|
+
if (!sourceUrl.scheme) {
|
|
2287
|
+
sourceUrl = [NSURL fileURLWithPath:rawUri];
|
|
2288
|
+
}
|
|
2289
|
+
|
|
2290
|
+
AVURLAsset *asset = [AVURLAsset URLAssetWithURL:sourceUrl options:nil];
|
|
2291
|
+
NSInteger count = options[@"count"] ? [options[@"count"] integerValue] : 10;
|
|
2292
|
+
if (count <= 0) count = 10;
|
|
2293
|
+
if (count > 50) count = 50;
|
|
2294
|
+
|
|
2295
|
+
CGFloat targetWidth = options[@"maxWidth"] ? [options[@"maxWidth"] doubleValue] : (options[@"targetWidth"] ? [options[@"targetWidth"] doubleValue] : 120);
|
|
2296
|
+
CGFloat targetHeight = options[@"maxHeight"] ? [options[@"maxHeight"] doubleValue] : (options[@"targetHeight"] ? [options[@"targetHeight"] doubleValue] : 120);
|
|
2297
|
+
CGFloat quality = options[@"quality"] ? [options[@"quality"] doubleValue] : 0.7;
|
|
2298
|
+
|
|
2299
|
+
double durationSeconds = CMTimeGetSeconds(asset.duration);
|
|
2300
|
+
if (durationSeconds <= 0) {
|
|
2301
|
+
reject(@"INVALID_DURATION", @"Unable to determine video duration", nil);
|
|
2302
|
+
return;
|
|
2303
|
+
}
|
|
2304
|
+
|
|
2305
|
+
AVAssetImageGenerator *generator = [AVAssetImageGenerator assetImageGeneratorWithAsset:asset];
|
|
2306
|
+
generator.appliesPreferredTrackTransform = YES;
|
|
2307
|
+
generator.maximumSize = CGSizeMake(targetWidth, targetHeight);
|
|
2308
|
+
generator.requestedTimeToleranceBefore = kCMTimeZero;
|
|
2309
|
+
generator.requestedTimeToleranceAfter = kCMTimeZero;
|
|
2310
|
+
|
|
2311
|
+
NSMutableArray *thumbnails = [NSMutableArray arrayWithCapacity:count];
|
|
2312
|
+
double step = durationSeconds / (double)count;
|
|
2313
|
+
|
|
2314
|
+
for (NSInteger i = 0; i < count; i++) {
|
|
2315
|
+
double targetSec = i * step;
|
|
2316
|
+
CMTime time = CMTimeMakeWithSeconds(targetSec, 600);
|
|
2317
|
+
NSError *genErr = nil;
|
|
2318
|
+
CGImageRef cgImage = [generator copyCGImageAtTime:time actualTime:NULL error:&genErr];
|
|
2319
|
+
if (cgImage) {
|
|
2320
|
+
UIImage *img = [UIImage imageWithCGImage:cgImage];
|
|
2321
|
+
CGImageRelease(cgImage);
|
|
2322
|
+
NSData *data = UIImageJPEGRepresentation(img, quality);
|
|
2323
|
+
NSString *b64 = [data base64EncodedStringWithOptions:0];
|
|
2324
|
+
NSString *dataUrl = [NSString stringWithFormat:@"data:image/jpeg;base64,%@", b64];
|
|
2325
|
+
[thumbnails addObject:@{
|
|
2326
|
+
@"timeMs": @(targetSec * 1000.0),
|
|
2327
|
+
@"uri": dataUrl,
|
|
2328
|
+
@"index": @(i),
|
|
2329
|
+
}];
|
|
2330
|
+
}
|
|
2331
|
+
}
|
|
2332
|
+
|
|
2333
|
+
resolve(@{
|
|
2334
|
+
@"thumbnails": thumbnails,
|
|
2335
|
+
@"durationMs": @(durationSeconds * 1000.0),
|
|
2336
|
+
});
|
|
2337
|
+
} @catch (NSException *ex) {
|
|
2338
|
+
reject(@"FILMSTRIP_FAILED", ex.reason ?: @"Filmstrip generation failed", nil);
|
|
2339
|
+
}
|
|
2340
|
+
});
|
|
2341
|
+
}
|
|
2342
|
+
|
|
1914
2343
|
|
|
1915
2344
|
#ifdef RCT_NEW_ARCH_ENABLED
|
|
1916
2345
|
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-inapp-inspector",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.5.1",
|
|
4
4
|
"description": "The zero-config, all-in-one in-app debugger & network logger for React Native & Expo (Flipper / Chucker alternative). Inspect Network (fetch/Axios/GraphQL), Console logs with Metro Symbolication, Redux State, Firebase Analytics, Storage (AsyncStorage/MMKV), Hardware Telemetry, and JS Bundle size directly on device.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -87,6 +87,13 @@
|
|
|
87
87
|
"require": "./dist/commonjs/socket.js",
|
|
88
88
|
"default": "./dist/commonjs/socket.js"
|
|
89
89
|
},
|
|
90
|
+
"./editor": {
|
|
91
|
+
"react-native": "./dist/commonjs/editor.js",
|
|
92
|
+
"types": "./dist/commonjs/editor.d.ts",
|
|
93
|
+
"import": "./dist/esm/editor.js",
|
|
94
|
+
"require": "./dist/commonjs/editor.js",
|
|
95
|
+
"default": "./dist/commonjs/editor.js"
|
|
96
|
+
},
|
|
90
97
|
"./metro": {
|
|
91
98
|
"types": "./dist/commonjs/metro.d.ts",
|
|
92
99
|
"import": "./dist/esm/metro.js",
|
|
@@ -102,6 +109,8 @@
|
|
|
102
109
|
"assets",
|
|
103
110
|
"metro.js",
|
|
104
111
|
"metro.d.ts",
|
|
112
|
+
"editor.js",
|
|
113
|
+
"editor.d.ts",
|
|
105
114
|
"README.md",
|
|
106
115
|
"android",
|
|
107
116
|
"ios",
|
|
@@ -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", "AVKit", "ReplayKit", "CoreMedia", "CoreVideo", "ImageIO", "MobileCoreServices", "QuartzCore"
|
|
16
|
+
s.frameworks = "AVFoundation", "AVKit", "ReplayKit", "CoreMedia", "CoreVideo", "ImageIO", "MobileCoreServices", "QuartzCore", "CoreImage"
|
|
17
17
|
|
|
18
18
|
# React Native New Architecture (TurboModules & Codegen) support
|
|
19
19
|
if respond_to?(:install_modules_dependencies, true)
|
|
@@ -42,7 +42,9 @@ export interface NativeCrashEvent {
|
|
|
42
42
|
|
|
43
43
|
// Seamless TurboModule (New Architecture / JSI) & Legacy NativeModules Bridge resolution
|
|
44
44
|
const NativeModule: any =
|
|
45
|
-
NativeNetworkInspector ||
|
|
45
|
+
NativeNetworkInspector ||
|
|
46
|
+
NativeModules.NetworkInspectorModule ||
|
|
47
|
+
NativeModules.NetworkInspector;
|
|
46
48
|
|
|
47
49
|
export const isNativeModuleAvailable = (): boolean => {
|
|
48
50
|
return !!NativeModule;
|
|
@@ -611,9 +613,9 @@ export const fetchCapturedMediaList = async (): Promise<CapturedMediaItem[]> =>
|
|
|
611
613
|
return [];
|
|
612
614
|
}
|
|
613
615
|
try {
|
|
614
|
-
const
|
|
615
|
-
if (!
|
|
616
|
-
const parsed = JSON.parse(
|
|
616
|
+
const raw: any = await NativeModule.getCapturedMedia();
|
|
617
|
+
if (!raw) return [];
|
|
618
|
+
const parsed = typeof raw === 'string' ? JSON.parse(raw) : raw;
|
|
617
619
|
return Array.isArray(parsed) ? parsed : [];
|
|
618
620
|
} catch {
|
|
619
621
|
return [];
|
|
@@ -666,4 +668,55 @@ export const copyMediaToClipboard = async (filePath: string): Promise<boolean> =
|
|
|
666
668
|
}
|
|
667
669
|
};
|
|
668
670
|
|
|
671
|
+
/**
|
|
672
|
+
* 100% Native photo editing (lossless crop, rotate, flip, and GPU color grading).
|
|
673
|
+
*/
|
|
674
|
+
export const editNativePhoto = async (
|
|
675
|
+
options: import('../types/editor').PhotoEditOptions,
|
|
676
|
+
): Promise<import('../types/editor').PhotoEditResult | null> => {
|
|
677
|
+
if (!NativeModule || !NativeModule.editPhoto) {
|
|
678
|
+
return null;
|
|
679
|
+
}
|
|
680
|
+
try {
|
|
681
|
+
const result = await NativeModule.editPhoto(options);
|
|
682
|
+
return result as import('../types/editor').PhotoEditResult;
|
|
683
|
+
} catch (err) {
|
|
684
|
+
return null;
|
|
685
|
+
}
|
|
686
|
+
};
|
|
687
|
+
|
|
688
|
+
/**
|
|
689
|
+
* 100% Native hardware-accelerated video trimming and export.
|
|
690
|
+
*/
|
|
691
|
+
export const trimNativeVideo = async (
|
|
692
|
+
options: import('../types/editor').VideoTrimOptions,
|
|
693
|
+
): Promise<import('../types/editor').VideoTrimResult | null> => {
|
|
694
|
+
if (!NativeModule || !NativeModule.trimVideo) {
|
|
695
|
+
return null;
|
|
696
|
+
}
|
|
697
|
+
try {
|
|
698
|
+
const result = await NativeModule.trimVideo(options);
|
|
699
|
+
return result as import('../types/editor').VideoTrimResult;
|
|
700
|
+
} catch (err) {
|
|
701
|
+
return null;
|
|
702
|
+
}
|
|
703
|
+
};
|
|
704
|
+
|
|
705
|
+
/**
|
|
706
|
+
* 100% Native video filmstrip thumbnail generator for timeline scrubbers.
|
|
707
|
+
*/
|
|
708
|
+
export const generateNativeFilmstrip = async (
|
|
709
|
+
options: import('../types/editor').FilmstripOptions,
|
|
710
|
+
): Promise<import('../types/editor').FilmstripResult | null> => {
|
|
711
|
+
if (!NativeModule || !NativeModule.generateFilmstrip) {
|
|
712
|
+
return null;
|
|
713
|
+
}
|
|
714
|
+
try {
|
|
715
|
+
const result = await NativeModule.generateFilmstrip(options);
|
|
716
|
+
return result as import('../types/editor').FilmstripResult;
|
|
717
|
+
} catch (err) {
|
|
718
|
+
return null;
|
|
719
|
+
}
|
|
720
|
+
};
|
|
721
|
+
|
|
669
722
|
|
|
@@ -26,6 +26,10 @@ export interface Spec extends TurboModule {
|
|
|
26
26
|
getCapturedMedia(): Promise<string>;
|
|
27
27
|
deleteCapturedMedia(uri: string): Promise<boolean>;
|
|
28
28
|
clearAllCapturedMedia(): Promise<boolean>;
|
|
29
|
+
copyMediaToClipboard(filePath: string): Promise<Object>;
|
|
30
|
+
editPhoto(options: Object): Promise<Object>;
|
|
31
|
+
trimVideo(options: Object): Promise<Object>;
|
|
32
|
+
generateFilmstrip(options: Object): Promise<Object>;
|
|
29
33
|
addListener(eventName: string): void;
|
|
30
34
|
removeListeners(count: number): void;
|
|
31
35
|
}
|