react-native-inapp-inspector 2.0.1 → 2.0.2
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/README.md +10 -0
- package/android/.gradle/8.9/checksums/checksums.lock +0 -0
- package/android/.gradle/8.9/checksums/md5-checksums.bin +0 -0
- package/android/.gradle/8.9/checksums/sha1-checksums.bin +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/build/reports/problems/problems-report.html +659 -0
- package/android/src/main/java/com/inappinspector/NetworkInspectorModule.kt +23 -0
- package/dist/commonjs/components/Inspector/MainScreen.js +4 -0
- package/dist/commonjs/components/Inspector/TelemetryConsentModal.d.ts +3 -0
- package/dist/commonjs/components/Inspector/TelemetryConsentModal.js +212 -0
- package/dist/commonjs/constants/version.d.ts +1 -1
- package/dist/commonjs/constants/version.js +1 -1
- package/dist/commonjs/helpers/index.d.ts +1 -0
- package/dist/commonjs/helpers/index.js +1 -0
- package/dist/commonjs/helpers/telemetry.d.ts +99 -0
- package/dist/commonjs/helpers/telemetry.js +398 -0
- package/dist/commonjs/index.d.ts +2 -0
- package/dist/commonjs/index.js +23 -1
- package/dist/commonjs/native/NativeInspector.d.ts +5 -0
- package/dist/commonjs/native/NativeInspector.js +3 -2
- package/dist/esm/components/Inspector/MainScreen.js +4 -0
- package/dist/esm/components/Inspector/TelemetryConsentModal.d.ts +3 -0
- package/dist/esm/components/Inspector/TelemetryConsentModal.js +175 -0
- package/dist/esm/constants/version.d.ts +1 -1
- package/dist/esm/constants/version.js +1 -1
- package/dist/esm/helpers/index.d.ts +1 -0
- package/dist/esm/helpers/index.js +1 -0
- package/dist/esm/helpers/telemetry.d.ts +99 -0
- package/dist/esm/helpers/telemetry.js +380 -0
- package/dist/esm/index.d.ts +2 -0
- package/dist/esm/index.js +13 -1
- package/dist/esm/native/NativeInspector.d.ts +5 -0
- package/dist/esm/native/NativeInspector.js +3 -2
- package/ios/{NetworkInspectorModule.m → NetworkInspectorModule.mm} +175 -119
- package/package.json +2 -2
package/dist/esm/index.js
CHANGED
|
@@ -8,7 +8,7 @@ import ErrorBoundary from './components/ErrorBoundary';
|
|
|
8
8
|
import MainScreen from './components/Inspector/MainScreen';
|
|
9
9
|
import { InspectorContext, animateNextLayout, } from './components/Inspector/InspectorContext';
|
|
10
10
|
// Helpers
|
|
11
|
-
import { formatDisplayUrl, getNavigationInfo, deduplicateLogs, getDomainColor, getEventCategory, matchNetworkLogQuery, } from './helpers';
|
|
11
|
+
import { formatDisplayUrl, getNavigationInfo, deduplicateLogs, getDomainColor, getEventCategory, matchNetworkLogQuery, sendSessionTelemetryPing, trackInspectorOpen, } from './helpers';
|
|
12
12
|
// #5 — settings persistence
|
|
13
13
|
import { loadSettings, saveSettings, setCustomStorage, clearPersistedSettings, calculateRamBasedLimits, } from './helpers/settingsStore';
|
|
14
14
|
import { getNativeSystemMetrics, pushNativeLogRecord, fetchNativeCachedPage, } from './native/NativeInspector';
|
|
@@ -699,6 +699,14 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
|
|
|
699
699
|
}, [unreadPulseAnim]);
|
|
700
700
|
const isNativeModule = useMemo(() => isNativeModuleAvailable(), []);
|
|
701
701
|
const useNativeFab = (Platform.OS === 'ios' || Platform.OS === 'android') && isNativeModule;
|
|
702
|
+
// Send anonymous initialization heartbeat to GA4 Measurement Protocol
|
|
703
|
+
useEffect(() => {
|
|
704
|
+
sendSessionTelemetryPing({
|
|
705
|
+
environment,
|
|
706
|
+
hasNavigation: Boolean(navigationRef),
|
|
707
|
+
hasAppIcon: Boolean(appIcon),
|
|
708
|
+
});
|
|
709
|
+
}, [environment, navigationRef, appIcon]);
|
|
702
710
|
// 100% Native Main-Thread Floating Button Lifecycle
|
|
703
711
|
useEffect(() => {
|
|
704
712
|
if (!useNativeFab || !isEnabled || !enabled) {
|
|
@@ -753,6 +761,8 @@ const NetworkInspector = ({ enabled = true, isEnabled = true, storage, navigatio
|
|
|
753
761
|
? defaultTab
|
|
754
762
|
: 'apis';
|
|
755
763
|
setActiveTab(target);
|
|
764
|
+
// Track inspector opened event in GA4
|
|
765
|
+
trackInspectorOpen({ activeTab: target });
|
|
756
766
|
// Instant synchronization of data collected while modal was closed
|
|
757
767
|
if (latestNetworkLogsRef.current.length > 0) {
|
|
758
768
|
const deduped = deduplicateLogs(latestNetworkLogsRef.current);
|
|
@@ -1739,4 +1749,6 @@ export { getEventCategory, registerGAPlugin, } from './helpers/gaAnalyticsRegist
|
|
|
1739
1749
|
export { usePerformanceTracker, useComponentProfiler, useNavigationProfiler, trackComponentRender, trackNavigationTransition, trackHeavyTask, measureAsync, getHermesMemoryStats, registerComponentProfile, subscribeRenderProfiles, getRenderProfiles, logPerformanceEvent, clearPerformanceEvents, subscribePerformanceEvents, getPerformanceEvents, getInitialRenderProfiles, getInitialPerformanceEvents, generateFixSnippet, } from './customHooks/performanceTracker';
|
|
1740
1750
|
export { InspectLog, InspectTrackTime, InspectCatch, } from './decorators';
|
|
1741
1751
|
export { getNativeDeviceMetrics, enableNativeCrashProtection, subscribeNativeCrashes, showNativeFloatingButton, hideNativeFloatingButton, setNativeFloatingButtonBadge, subscribeNativeFloatingButtonPress, subscribeNativeDeviceShake, startNativeFpsMonitoring, stopNativeFpsMonitoring, getNativeFpsMetrics, getNativeStorageItem, setNativeStorageItem, isNativeModuleAvailable, } from './native/NativeInspector';
|
|
1752
|
+
export { sendSessionTelemetryPing, trackTelemetryEvent, trackInspectorOpen, trackTabSwitch, trackLogExport, GA4_MEASUREMENT_ID, GA4_API_SECRET, } from './helpers';
|
|
1753
|
+
export { BrandSquareIcon, BrandCircleIcon, } from './components/NetworkIcons';
|
|
1742
1754
|
export { ActiveTab, Method, StatusFilter, SortOrder, LocalFilter, ModalAnimationType, SettingsPage, SettingsSubTab, LogFilter, ConsoleLogType, AnalyticsEventSource, GAEventCategory, StackFrameType, DiffResultType, BundleSubTab, PerformanceSubTab, CrashType, CrashExportFormat, CrashDetailSubTab, CrashFilterType, BreadcrumbType, } from './types';
|
|
@@ -17,6 +17,11 @@ export interface NativeDeviceMetrics {
|
|
|
17
17
|
osVersion?: string;
|
|
18
18
|
apiLevel?: number;
|
|
19
19
|
cpuAbi?: string;
|
|
20
|
+
appName?: string;
|
|
21
|
+
appVersion?: string;
|
|
22
|
+
appBuild?: string;
|
|
23
|
+
appBundleId?: string;
|
|
24
|
+
appPackageName?: string;
|
|
20
25
|
}
|
|
21
26
|
export interface NativeCrashEvent {
|
|
22
27
|
platform: 'android' | 'ios';
|
|
@@ -5,8 +5,9 @@ const NativeModule = NativeNetworkInspector || NativeModules.NetworkInspectorMod
|
|
|
5
5
|
export const isNativeModuleAvailable = () => {
|
|
6
6
|
return !!NativeModule;
|
|
7
7
|
};
|
|
8
|
-
const
|
|
9
|
-
|
|
8
|
+
const eventTarget = NativeModules.NetworkInspectorModule || NativeNetworkInspector;
|
|
9
|
+
const nativeEmitter = eventTarget
|
|
10
|
+
? new NativeEventEmitter(eventTarget)
|
|
10
11
|
: null;
|
|
11
12
|
/**
|
|
12
13
|
* Retrieves low-level native hardware and system metrics (RAM, Heap, Disk, Battery, CPU).
|
|
@@ -21,6 +21,8 @@ static NSUncaughtExceptionHandler *previousUncaughtExceptionHandler = NULL;
|
|
|
21
21
|
if (self = [super initWithFrame:frame]) {
|
|
22
22
|
self.backgroundColor = [UIColor clearColor];
|
|
23
23
|
self.userInteractionEnabled = NO;
|
|
24
|
+
self.contentMode = UIViewContentModeRedraw;
|
|
25
|
+
self.clipsToBounds = NO;
|
|
24
26
|
}
|
|
25
27
|
return self;
|
|
26
28
|
}
|
|
@@ -177,11 +179,9 @@ static NSUncaughtExceptionHandler *previousUncaughtExceptionHandler = NULL;
|
|
|
177
179
|
|
|
178
180
|
@end
|
|
179
181
|
|
|
180
|
-
@interface InAppInspectorFloatingView ()
|
|
181
|
-
@property (nonatomic, assign) CGPoint
|
|
182
|
-
@property (nonatomic, assign)
|
|
183
|
-
@property (nonatomic, assign) NSTimeInterval touchDownTime;
|
|
184
|
-
@property (nonatomic, assign) BOOL isDragging;
|
|
182
|
+
@interface InAppInspectorFloatingView () <UIGestureRecognizerDelegate>
|
|
183
|
+
@property (nonatomic, assign) CGPoint panStartCenter;
|
|
184
|
+
@property (nonatomic, assign) NSTimeInterval lastTapTime;
|
|
185
185
|
@end
|
|
186
186
|
|
|
187
187
|
@implementation InAppInspectorFloatingView
|
|
@@ -203,88 +203,100 @@ static NSUncaughtExceptionHandler *previousUncaughtExceptionHandler = NULL;
|
|
|
203
203
|
self.layer.borderWidth = 2.2;
|
|
204
204
|
self.layer.borderColor = [UIColor colorWithRed:56.0/255.0 green:189.0/255.0 blue:248.0/255.0 alpha:0.9].CGColor;
|
|
205
205
|
|
|
206
|
-
// Native drawn Inspector Owl icon
|
|
206
|
+
// Native drawn Inspector Owl icon
|
|
207
207
|
CGFloat iconSize = frame.size.width * 0.94;
|
|
208
208
|
CGFloat iconOffset = (frame.size.width - iconSize) / 2.0;
|
|
209
209
|
InAppInspectorOwlView *owlView = [[InAppInspectorOwlView alloc] initWithFrame:CGRectMake(iconOffset, iconOffset, iconSize, iconSize)];
|
|
210
210
|
owlView.userInteractionEnabled = NO;
|
|
211
211
|
[self addSubview:owlView];
|
|
212
|
+
|
|
213
|
+
// Dedicated Tap Gesture Recognizer
|
|
214
|
+
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapGesture:)];
|
|
215
|
+
tap.numberOfTapsRequired = 1;
|
|
216
|
+
tap.cancelsTouchesInView = NO;
|
|
217
|
+
tap.delegate = self;
|
|
218
|
+
[self addGestureRecognizer:tap];
|
|
219
|
+
|
|
220
|
+
// Dedicated Pan Gesture Recognizer
|
|
221
|
+
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanGesture:)];
|
|
222
|
+
pan.delegate = self;
|
|
223
|
+
[self addGestureRecognizer:pan];
|
|
212
224
|
}
|
|
213
225
|
return self;
|
|
214
226
|
}
|
|
215
227
|
|
|
228
|
+
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
|
|
229
|
+
if (!self.userInteractionEnabled || self.hidden || self.alpha < 0.01) {
|
|
230
|
+
return nil;
|
|
231
|
+
}
|
|
232
|
+
if (CGRectContainsPoint(self.bounds, point)) {
|
|
233
|
+
return self;
|
|
234
|
+
}
|
|
235
|
+
return [super hitTest:point withEvent:event];
|
|
236
|
+
}
|
|
237
|
+
|
|
216
238
|
- (void)updateBadgeVisible:(BOOL)visible {
|
|
217
|
-
// Active badge dot
|
|
239
|
+
// Active badge dot
|
|
218
240
|
}
|
|
219
241
|
|
|
220
|
-
- (void)
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
if (self.superview) {
|
|
225
|
-
[self.superview bringSubviewToFront:self];
|
|
242
|
+
- (void)handleTapGesture:(UITapGestureRecognizer *)gesture {
|
|
243
|
+
if (gesture.state == UIGestureRecognizerStateEnded) {
|
|
244
|
+
[self triggerTapAction];
|
|
226
245
|
}
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
self.
|
|
232
|
-
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
- (void)triggerTapAction {
|
|
249
|
+
NSTimeInterval now = CACurrentMediaTime();
|
|
250
|
+
if (now - self.lastTapTime < 0.35) return;
|
|
251
|
+
self.lastTapTime = now;
|
|
252
|
+
|
|
253
|
+
if (@available(iOS 10.0, *)) {
|
|
254
|
+
UIImpactFeedbackGenerator *impact = [[UIImpactFeedbackGenerator alloc] initWithStyle:UIImpactFeedbackStyleMedium];
|
|
255
|
+
[impact prepare];
|
|
256
|
+
[impact impactOccurred];
|
|
257
|
+
}
|
|
258
|
+
|
|
233
259
|
[UIView animateWithDuration:0.08 animations:^{
|
|
234
|
-
self.transform = CGAffineTransformMakeScale(0.
|
|
260
|
+
self.transform = CGAffineTransformMakeScale(0.90, 0.90);
|
|
261
|
+
} completion:^(BOOL finished) {
|
|
262
|
+
[UIView animateWithDuration:0.10 animations:^{
|
|
263
|
+
self.transform = CGAffineTransformIdentity;
|
|
264
|
+
}];
|
|
235
265
|
}];
|
|
266
|
+
|
|
267
|
+
if (self.onTapBlock) {
|
|
268
|
+
self.onTapBlock();
|
|
269
|
+
}
|
|
236
270
|
}
|
|
237
271
|
|
|
238
|
-
- (void)
|
|
239
|
-
UITouch *touch = [touches anyObject];
|
|
272
|
+
- (void)handlePanGesture:(UIPanGestureRecognizer *)pan {
|
|
240
273
|
UIView *superview = self.superview;
|
|
241
|
-
if (!
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
if (self.isDragging) {
|
|
274
|
+
if (!superview) return;
|
|
275
|
+
|
|
276
|
+
if (pan.state == UIGestureRecognizerStateBegan) {
|
|
277
|
+
self.panStartCenter = self.center;
|
|
278
|
+
[superview bringSubviewToFront:self];
|
|
279
|
+
[UIView animateWithDuration:0.1 animations:^{
|
|
280
|
+
self.transform = CGAffineTransformMakeScale(1.06, 1.06);
|
|
281
|
+
}];
|
|
282
|
+
} else if (pan.state == UIGestureRecognizerStateChanged) {
|
|
283
|
+
CGPoint translation = [pan translationInView:superview];
|
|
253
284
|
CGFloat halfW = self.bounds.size.width / 2.0;
|
|
254
285
|
CGFloat halfH = self.bounds.size.height / 2.0;
|
|
255
286
|
CGFloat minX = halfW + 10.0;
|
|
256
287
|
CGFloat maxX = superview.bounds.size.width - halfW - 10.0;
|
|
257
288
|
CGFloat minY = halfH + 44.0;
|
|
258
289
|
CGFloat maxY = superview.bounds.size.height - halfH - 44.0;
|
|
259
|
-
|
|
260
|
-
CGPoint newCenter = CGPointMake(self.
|
|
290
|
+
|
|
291
|
+
CGPoint newCenter = CGPointMake(self.panStartCenter.x + translation.x, self.panStartCenter.y + translation.y);
|
|
261
292
|
newCenter.x = MAX(minX, MIN(maxX, newCenter.x));
|
|
262
293
|
newCenter.y = MAX(minY, MIN(maxY, newCenter.y));
|
|
263
294
|
self.center = newCenter;
|
|
264
|
-
}
|
|
265
|
-
|
|
295
|
+
} else if (pan.state == UIGestureRecognizerStateEnded || pan.state == UIGestureRecognizerStateCancelled) {
|
|
296
|
+
[UIView animateWithDuration:0.15 animations:^{
|
|
297
|
+
self.transform = CGAffineTransformIdentity;
|
|
298
|
+
}];
|
|
266
299
|
|
|
267
|
-
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
|
|
268
|
-
UITouch *touch = [touches anyObject];
|
|
269
|
-
UIView *superview = self.superview;
|
|
270
|
-
|
|
271
|
-
[UIView animateWithDuration:0.12 animations:^{
|
|
272
|
-
self.transform = CGAffineTransformIdentity;
|
|
273
|
-
}];
|
|
274
|
-
|
|
275
|
-
if (!touch || !superview) return;
|
|
276
|
-
|
|
277
|
-
CGPoint currentPoint = [touch locationInView:self.window];
|
|
278
|
-
CGFloat dx = currentPoint.x - self.touchDownPoint.x;
|
|
279
|
-
CGFloat dy = currentPoint.y - self.touchDownPoint.y;
|
|
280
|
-
CGFloat distance = hypot(dx, dy);
|
|
281
|
-
NSTimeInterval elapsed = CACurrentMediaTime() - self.touchDownTime;
|
|
282
|
-
|
|
283
|
-
if (!self.isDragging && distance < 24.0 && elapsed < 0.85) {
|
|
284
|
-
if (self.onTapBlock) {
|
|
285
|
-
self.onTapBlock();
|
|
286
|
-
}
|
|
287
|
-
} else if (self.isDragging) {
|
|
288
300
|
CGFloat halfW = self.bounds.size.width / 2.0;
|
|
289
301
|
CGFloat minX = halfW + 10.0;
|
|
290
302
|
CGFloat maxX = superview.bounds.size.width - halfW - 10.0;
|
|
@@ -295,12 +307,6 @@ static NSUncaughtExceptionHandler *previousUncaughtExceptionHandler = NULL;
|
|
|
295
307
|
}
|
|
296
308
|
}
|
|
297
309
|
|
|
298
|
-
- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
|
|
299
|
-
[UIView animateWithDuration:0.12 animations:^{
|
|
300
|
-
self.transform = CGAffineTransformIdentity;
|
|
301
|
-
}];
|
|
302
|
-
}
|
|
303
|
-
|
|
304
310
|
@end
|
|
305
311
|
|
|
306
312
|
static InAppInspectorFloatingView *floatingButtonView = nil;
|
|
@@ -451,13 +457,13 @@ RCT_EXPORT_MODULE(NetworkInspectorModule);
|
|
|
451
457
|
}
|
|
452
458
|
|
|
453
459
|
RCT_EXPORT_METHOD(enableNativeCrashProtection:(RCTPromiseResolveBlock)resolve
|
|
454
|
-
|
|
460
|
+
reject:(RCTPromiseRejectBlock)reject) {
|
|
455
461
|
[self installHandlers];
|
|
456
462
|
resolve(@(YES));
|
|
457
463
|
}
|
|
458
464
|
|
|
459
465
|
RCT_EXPORT_METHOD(getDeviceMetrics:(RCTPromiseResolveBlock)resolve
|
|
460
|
-
|
|
466
|
+
reject:(RCTPromiseRejectBlock)reject) {
|
|
461
467
|
NSMutableDictionary *metrics = [NSMutableDictionary dictionary];
|
|
462
468
|
|
|
463
469
|
// 1. Memory / RAM Metrics
|
|
@@ -510,46 +516,66 @@ RCT_EXPORT_METHOD(getDeviceMetrics:(RCTPromiseResolveBlock)resolve
|
|
|
510
516
|
[metrics setObject:[UIDevice currentDevice].systemVersion forKey:@"osVersion"];
|
|
511
517
|
[metrics setObject:@"arm64" forKey:@"cpuAbi"];
|
|
512
518
|
|
|
519
|
+
// 5. Application Identifiers (Legal & Non-PII)
|
|
520
|
+
NSBundle *mainBundle = [NSBundle mainBundle];
|
|
521
|
+
NSString *appName = [mainBundle objectForInfoDictionaryKey:@"CFBundleDisplayName"] ?: [mainBundle objectForInfoDictionaryKey:@"CFBundleName"];
|
|
522
|
+
NSString *appVersion = [mainBundle objectForInfoDictionaryKey:@"CFBundleShortVersionString"];
|
|
523
|
+
NSString *appBuild = [mainBundle objectForInfoDictionaryKey:@"CFBundleVersion"];
|
|
524
|
+
NSString *appBundleId = [mainBundle bundleIdentifier];
|
|
525
|
+
if (appName) [metrics setObject:appName forKey:@"appName"];
|
|
526
|
+
if (appVersion) [metrics setObject:appVersion forKey:@"appVersion"];
|
|
527
|
+
if (appBuild) [metrics setObject:appBuild forKey:@"appBuild"];
|
|
528
|
+
if (appBundleId) {
|
|
529
|
+
[metrics setObject:appBundleId forKey:@"appBundleId"];
|
|
530
|
+
[metrics setObject:appBundleId forKey:@"appPackageName"];
|
|
531
|
+
}
|
|
532
|
+
|
|
513
533
|
resolve(metrics);
|
|
514
534
|
}
|
|
515
535
|
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
for (UIWindow *w in scene.windows) {
|
|
525
|
-
if (w.isKeyWindow) {
|
|
526
|
-
targetWindow = w;
|
|
527
|
-
break;
|
|
528
|
-
}
|
|
536
|
+
static UIWindow *GetAppActiveWindow(void) {
|
|
537
|
+
if (@available(iOS 13.0, *)) {
|
|
538
|
+
for (UIScene *scene in [UIApplication sharedApplication].connectedScenes) {
|
|
539
|
+
if ([scene isKindOfClass:[UIWindowScene class]]) {
|
|
540
|
+
UIWindowScene *ws = (UIWindowScene *)scene;
|
|
541
|
+
for (UIWindow *w in ws.windows) {
|
|
542
|
+
if (w.isKeyWindow || w.windowLevel == UIWindowLevelNormal) {
|
|
543
|
+
return w;
|
|
529
544
|
}
|
|
530
545
|
}
|
|
531
|
-
if (
|
|
546
|
+
if (ws.windows.count > 0) {
|
|
547
|
+
return ws.windows.firstObject;
|
|
548
|
+
}
|
|
532
549
|
}
|
|
533
550
|
}
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
}
|
|
551
|
+
}
|
|
552
|
+
for (UIWindow *w in [UIApplication sharedApplication].windows) {
|
|
553
|
+
if (w.isKeyWindow || w.windowLevel == UIWindowLevelNormal) {
|
|
554
|
+
return w;
|
|
539
555
|
}
|
|
556
|
+
}
|
|
557
|
+
return [UIApplication sharedApplication].windows.firstObject;
|
|
558
|
+
}
|
|
540
559
|
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
560
|
+
RCT_EXPORT_METHOD(showFloatingButton:(NSDictionary *)options
|
|
561
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
562
|
+
reject:(RCTPromiseRejectBlock)reject) {
|
|
563
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
564
|
+
UIWindow *targetWindow = GetAppActiveWindow();
|
|
565
|
+
CGRect screenBounds = targetWindow ? targetWindow.bounds : [UIScreen mainScreen].bounds;
|
|
566
|
+
|
|
567
|
+
CGFloat screenWidth = screenBounds.size.width > 0 ? screenBounds.size.width : [UIScreen mainScreen].bounds.size.width;
|
|
568
|
+
if (screenWidth <= 0) screenWidth = 393.0;
|
|
569
|
+
CGFloat screenHeight = screenBounds.size.height > 0 ? screenBounds.size.height : [UIScreen mainScreen].bounds.size.height;
|
|
570
|
+
if (screenHeight <= 0) screenHeight = 852.0;
|
|
545
571
|
|
|
546
572
|
CGFloat size = 64.0;
|
|
547
573
|
if (options && options[@"size"]) {
|
|
548
574
|
size = [options[@"size"] doubleValue];
|
|
549
575
|
}
|
|
550
576
|
|
|
551
|
-
CGFloat initialX =
|
|
552
|
-
CGFloat initialY =
|
|
577
|
+
CGFloat initialX = screenWidth - size - 20.0;
|
|
578
|
+
CGFloat initialY = screenHeight - size - 120.0;
|
|
553
579
|
if (options && options[@"x"]) {
|
|
554
580
|
initialX = [options[@"x"] doubleValue];
|
|
555
581
|
}
|
|
@@ -559,6 +585,7 @@ RCT_EXPORT_METHOD(showFloatingButton:(NSDictionary *)options
|
|
|
559
585
|
|
|
560
586
|
if (floatingButtonView == nil) {
|
|
561
587
|
floatingButtonView = [[InAppInspectorFloatingView alloc] initWithFrame:CGRectMake(initialX, initialY, size, size)];
|
|
588
|
+
floatingButtonView.layer.zPosition = 999999;
|
|
562
589
|
__weak NetworkInspectorModule *weakSelf = self;
|
|
563
590
|
floatingButtonView.onTapBlock = ^{
|
|
564
591
|
NetworkInspectorModule *strongSelf = weakSelf ?: sharedInstance;
|
|
@@ -566,26 +593,47 @@ RCT_EXPORT_METHOD(showFloatingButton:(NSDictionary *)options
|
|
|
566
593
|
[strongSelf sendEventWithName:@"onFloatingButtonPress" body:@{}];
|
|
567
594
|
}
|
|
568
595
|
};
|
|
569
|
-
}
|
|
570
|
-
|
|
571
|
-
if (floatingButtonView.superview == nil) {
|
|
572
|
-
[targetWindow addSubview:floatingButtonView];
|
|
573
596
|
} else {
|
|
574
|
-
|
|
597
|
+
floatingButtonView.layer.zPosition = 999999;
|
|
598
|
+
floatingButtonView.frame = CGRectMake(initialX, initialY, size, size);
|
|
575
599
|
}
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
600
|
+
|
|
601
|
+
void (^attachToWindow)(void) = ^{
|
|
602
|
+
UIWindow *activeWin = GetAppActiveWindow();
|
|
603
|
+
if (!activeWin || !floatingButtonView) return;
|
|
604
|
+
|
|
605
|
+
CGRect winBounds = activeWin.bounds;
|
|
606
|
+
if (winBounds.size.width > 0 && winBounds.size.height > 0) {
|
|
607
|
+
CGRect curFrame = floatingButtonView.frame;
|
|
608
|
+
if (curFrame.origin.x <= 0 || curFrame.origin.x >= winBounds.size.width ||
|
|
609
|
+
curFrame.origin.y <= 0 || curFrame.origin.y >= winBounds.size.height) {
|
|
610
|
+
floatingButtonView.frame = CGRectMake(winBounds.size.width - curFrame.size.width - 20.0,
|
|
611
|
+
winBounds.size.height - curFrame.size.height - 120.0,
|
|
612
|
+
curFrame.size.width,
|
|
613
|
+
curFrame.size.height);
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
if (floatingButtonView.superview != activeWin) {
|
|
618
|
+
[activeWin addSubview:floatingButtonView];
|
|
619
|
+
}
|
|
620
|
+
[activeWin bringSubviewToFront:floatingButtonView];
|
|
621
|
+
floatingButtonView.hidden = NO;
|
|
580
622
|
floatingButtonView.alpha = 1.0;
|
|
581
|
-
|
|
623
|
+
[floatingButtonView.subviews.firstObject setNeedsDisplay];
|
|
624
|
+
};
|
|
625
|
+
|
|
626
|
+
attachToWindow();
|
|
627
|
+
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), attachToWindow);
|
|
628
|
+
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.8 * NSEC_PER_SEC)), dispatch_get_main_queue(), attachToWindow);
|
|
629
|
+
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), attachToWindow);
|
|
582
630
|
|
|
583
631
|
resolve(@(YES));
|
|
584
632
|
});
|
|
585
633
|
}
|
|
586
634
|
|
|
587
635
|
RCT_EXPORT_METHOD(hideFloatingButton:(RCTPromiseResolveBlock)resolve
|
|
588
|
-
|
|
636
|
+
reject:(RCTPromiseRejectBlock)reject) {
|
|
589
637
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
590
638
|
if (floatingButtonView != nil) {
|
|
591
639
|
[UIView animateWithDuration:0.15 animations:^{
|
|
@@ -599,8 +647,8 @@ RCT_EXPORT_METHOD(hideFloatingButton:(RCTPromiseResolveBlock)resolve
|
|
|
599
647
|
}
|
|
600
648
|
|
|
601
649
|
RCT_EXPORT_METHOD(setFloatingButtonBadge:(BOOL)hasBadge
|
|
602
|
-
|
|
603
|
-
|
|
650
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
651
|
+
reject:(RCTPromiseRejectBlock)reject) {
|
|
604
652
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
605
653
|
if (floatingButtonView != nil) {
|
|
606
654
|
[floatingButtonView updateBadgeVisible:hasBadge];
|
|
@@ -610,8 +658,8 @@ RCT_EXPORT_METHOD(setFloatingButtonBadge:(BOOL)hasBadge
|
|
|
610
658
|
}
|
|
611
659
|
|
|
612
660
|
RCT_EXPORT_METHOD(setFloatingButtonPosition:(double)x y:(double)y
|
|
613
|
-
|
|
614
|
-
|
|
661
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
662
|
+
reject:(RCTPromiseRejectBlock)reject) {
|
|
615
663
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
616
664
|
if (floatingButtonView != nil && floatingButtonView.superview != nil) {
|
|
617
665
|
floatingButtonView.frame = CGRectMake(x, y, floatingButtonView.frame.size.width, floatingButtonView.frame.size.height);
|
|
@@ -621,7 +669,7 @@ RCT_EXPORT_METHOD(setFloatingButtonPosition:(double)x y:(double)y
|
|
|
621
669
|
}
|
|
622
670
|
|
|
623
671
|
RCT_EXPORT_METHOD(startFpsMonitoring:(RCTPromiseResolveBlock)resolve
|
|
624
|
-
|
|
672
|
+
reject:(RCTPromiseRejectBlock)reject) {
|
|
625
673
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
626
674
|
if (self->displayLink == nil) {
|
|
627
675
|
self->lastFpsTimestamp = 0;
|
|
@@ -649,7 +697,7 @@ RCT_EXPORT_METHOD(startFpsMonitoring:(RCTPromiseResolveBlock)resolve
|
|
|
649
697
|
}
|
|
650
698
|
|
|
651
699
|
RCT_EXPORT_METHOD(stopFpsMonitoring:(RCTPromiseResolveBlock)resolve
|
|
652
|
-
|
|
700
|
+
reject:(RCTPromiseRejectBlock)reject) {
|
|
653
701
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
654
702
|
if (self->displayLink != nil) {
|
|
655
703
|
[self->displayLink invalidate];
|
|
@@ -660,7 +708,7 @@ RCT_EXPORT_METHOD(stopFpsMonitoring:(RCTPromiseResolveBlock)resolve
|
|
|
660
708
|
}
|
|
661
709
|
|
|
662
710
|
RCT_EXPORT_METHOD(getFpsMetrics:(RCTPromiseResolveBlock)resolve
|
|
663
|
-
|
|
711
|
+
reject:(RCTPromiseRejectBlock)reject) {
|
|
664
712
|
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
|
|
665
713
|
[dict setObject:@(self->currentCalculatedFps > 0 ? self->currentCalculatedFps : 60.0) forKey:@"fps"];
|
|
666
714
|
[dict setObject:@(60.0) forKey:@"targetFps"];
|
|
@@ -668,8 +716,8 @@ RCT_EXPORT_METHOD(getFpsMetrics:(RCTPromiseResolveBlock)resolve
|
|
|
668
716
|
}
|
|
669
717
|
|
|
670
718
|
RCT_EXPORT_METHOD(getNativeStorageItem:(NSString *)key
|
|
671
|
-
|
|
672
|
-
|
|
719
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
720
|
+
reject:(RCTPromiseRejectBlock)reject) {
|
|
673
721
|
NSString *prefKey = [NSString stringWithFormat:@"inapp_inspector_%@", key ?: @""];
|
|
674
722
|
NSString *val = [[NSUserDefaults standardUserDefaults] stringForKey:prefKey];
|
|
675
723
|
resolve(val ?: [NSNull null]);
|
|
@@ -677,8 +725,8 @@ RCT_EXPORT_METHOD(getNativeStorageItem:(NSString *)key
|
|
|
677
725
|
|
|
678
726
|
RCT_EXPORT_METHOD(setNativeStorageItem:(NSString *)key
|
|
679
727
|
value:(NSString *)value
|
|
680
|
-
|
|
681
|
-
|
|
728
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
729
|
+
reject:(RCTPromiseRejectBlock)reject) {
|
|
682
730
|
NSString *prefKey = [NSString stringWithFormat:@"inapp_inspector_%@", key ?: @""];
|
|
683
731
|
if (value == nil || [value isKindOfClass:[NSNull class]]) {
|
|
684
732
|
[[NSUserDefaults standardUserDefaults] removeObjectForKey:prefKey];
|
|
@@ -690,8 +738,8 @@ RCT_EXPORT_METHOD(setNativeStorageItem:(NSString *)key
|
|
|
690
738
|
}
|
|
691
739
|
|
|
692
740
|
RCT_EXPORT_METHOD(triggerHaptic:(NSString *)style
|
|
693
|
-
|
|
694
|
-
|
|
741
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
742
|
+
reject:(RCTPromiseRejectBlock)reject) {
|
|
695
743
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
696
744
|
if (@available(iOS 10.0, *)) {
|
|
697
745
|
NSString *s = [style lowercaseString] ?: @"light";
|
|
@@ -725,8 +773,16 @@ RCT_EXPORT_METHOD(triggerHaptic:(NSString *)style
|
|
|
725
773
|
});
|
|
726
774
|
}
|
|
727
775
|
|
|
776
|
+
RCT_EXPORT_METHOD(addListener:(NSString *)eventName) {
|
|
777
|
+
[super addListener:eventName];
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
RCT_EXPORT_METHOD(removeListeners:(double)count) {
|
|
781
|
+
[super removeListeners:count];
|
|
782
|
+
}
|
|
783
|
+
|
|
728
784
|
RCT_EXPORT_METHOD(getNativeSystemMetrics:(RCTPromiseResolveBlock)resolve
|
|
729
|
-
|
|
785
|
+
reject:(RCTPromiseRejectBlock)reject) {
|
|
730
786
|
dispatch_async(self->_metricsQueue, ^{
|
|
731
787
|
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
|
|
732
788
|
|
|
@@ -813,8 +869,8 @@ RCT_EXPORT_METHOD(pushNativeLogRecord:(NSString *)pageKey
|
|
|
813
869
|
}
|
|
814
870
|
|
|
815
871
|
RCT_EXPORT_METHOD(getNativeCachedPage:(NSString *)pageKey
|
|
816
|
-
offset:(
|
|
817
|
-
limit:(
|
|
872
|
+
offset:(double)offset
|
|
873
|
+
limit:(double)limit
|
|
818
874
|
query:(NSString *)query
|
|
819
875
|
resolve:(RCTPromiseResolveBlock)resolve
|
|
820
876
|
reject:(RCTPromiseRejectBlock)reject) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-inapp-inspector",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.2",
|
|
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",
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"scripts": {
|
|
44
44
|
"clean": "rm -rf dist",
|
|
45
45
|
"prebuild": "node scripts/gen-version.js",
|
|
46
|
-
"build": "npm run clean && tsc && tsc -p tsconfig.esm.json",
|
|
46
|
+
"build": "npm run clean && tsc && tsc -p tsconfig.esm.json && node scripts/inject-telemetry.js",
|
|
47
47
|
"watch": "tsc -w",
|
|
48
48
|
"prepack": "npm run build",
|
|
49
49
|
"publish": "node release.cjs",
|