react-native-inapp-inspector 1.1.28 → 1.1.31
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.java +29 -80
- package/dist/commonjs/components/AnalyticsDetail.js +668 -108
- package/dist/commonjs/components/AppHeaderLogo.js +15 -15
- package/dist/commonjs/components/ConsoleLogCard.js +112 -66
- package/dist/commonjs/components/CopyButton.js +15 -1
- package/dist/commonjs/components/DomainHeader.js +64 -32
- package/dist/commonjs/components/HighlightText.js +7 -1
- package/dist/commonjs/components/Inspector/AnalyticsTab.js +332 -221
- package/dist/commonjs/components/Inspector/ConsoleTab.js +162 -56
- package/dist/commonjs/components/Inspector/InspectorHeader.js +70 -119
- package/dist/commonjs/components/Inspector/LogDetail.js +53 -17
- package/dist/commonjs/components/Inspector/MainScreen.js +4 -0
- package/dist/commonjs/components/Inspector/NetworkDetail.js +24 -24
- package/dist/commonjs/components/Inspector/NetworkTab.js +4 -1
- package/dist/commonjs/components/Inspector/ReduxDetail.js +237 -42
- package/dist/commonjs/components/Inspector/ReduxTab.js +456 -35
- package/dist/commonjs/components/JsonViewer.js +26 -4
- package/dist/commonjs/components/LogCard.js +103 -11
- package/dist/commonjs/components/NetworkIcons.js +19 -10
- package/dist/commonjs/components/Toast.d.ts +3 -0
- package/dist/commonjs/components/Toast.js +152 -0
- package/dist/commonjs/components/TouchableScale.d.ts +1 -0
- package/dist/commonjs/components/TouchableScale.js +3 -3
- package/dist/commonjs/components/TreeNode.js +12 -2
- package/dist/commonjs/constants/index.js +6 -6
- package/dist/commonjs/constants/version.d.ts +1 -1
- package/dist/commonjs/constants/version.js +1 -1
- package/dist/commonjs/customHooks/reduxLogger.js +128 -5
- package/dist/commonjs/helpers/index.d.ts +4 -0
- package/dist/commonjs/helpers/index.js +107 -92
- package/dist/commonjs/helpers/toast.d.ts +4 -0
- package/dist/commonjs/helpers/toast.js +20 -0
- package/dist/commonjs/i18n/locales/en.json +49 -3
- package/dist/commonjs/styles/AppColors.d.ts +6 -0
- package/dist/commonjs/styles/AppColors.js +6 -0
- package/dist/commonjs/styles/index.d.ts +82 -15
- package/dist/commonjs/styles/index.js +92 -26
- package/dist/commonjs/types/interfaces.d.ts +7 -0
- package/dist/esm/components/AnalyticsDetail.js +670 -110
- package/dist/esm/components/AppHeaderLogo.js +15 -15
- package/dist/esm/components/ConsoleLogCard.js +114 -68
- package/dist/esm/components/CopyButton.js +15 -1
- package/dist/esm/components/DomainHeader.js +64 -32
- package/dist/esm/components/HighlightText.js +7 -1
- package/dist/esm/components/Inspector/AnalyticsTab.js +334 -223
- package/dist/esm/components/Inspector/ConsoleTab.js +163 -57
- package/dist/esm/components/Inspector/InspectorHeader.js +71 -120
- package/dist/esm/components/Inspector/LogDetail.js +55 -19
- package/dist/esm/components/Inspector/MainScreen.js +4 -0
- package/dist/esm/components/Inspector/NetworkDetail.js +25 -25
- package/dist/esm/components/Inspector/NetworkTab.js +4 -1
- package/dist/esm/components/Inspector/ReduxDetail.js +239 -44
- package/dist/esm/components/Inspector/ReduxTab.js +458 -37
- package/dist/esm/components/JsonViewer.js +26 -4
- package/dist/esm/components/LogCard.js +105 -13
- package/dist/esm/components/NetworkIcons.js +19 -10
- package/dist/esm/components/Toast.d.ts +3 -0
- package/dist/esm/components/Toast.js +117 -0
- package/dist/esm/components/TouchableScale.d.ts +1 -0
- package/dist/esm/components/TouchableScale.js +3 -3
- package/dist/esm/components/TreeNode.js +12 -2
- package/dist/esm/constants/index.js +6 -6
- package/dist/esm/constants/version.d.ts +1 -1
- package/dist/esm/constants/version.js +1 -1
- package/dist/esm/customHooks/reduxLogger.js +128 -5
- package/dist/esm/helpers/index.d.ts +4 -0
- package/dist/esm/helpers/index.js +102 -92
- package/dist/esm/helpers/toast.d.ts +4 -0
- package/dist/esm/helpers/toast.js +15 -0
- package/dist/esm/i18n/locales/en.json +49 -3
- package/dist/esm/styles/AppColors.d.ts +6 -0
- package/dist/esm/styles/AppColors.js +6 -0
- package/dist/esm/styles/index.d.ts +82 -15
- package/dist/esm/styles/index.js +92 -26
- package/dist/esm/types/interfaces.d.ts +7 -0
- package/ios/NetworkInspectorModule.m +0 -10
- package/package.json +13 -10
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
// and per-reducer "last action" consistently.
|
|
15
15
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
16
|
exports.connectReduxStore = exports.inspectorReduxMiddleware = exports.subscribeReduxState = exports.setReduxState = exports.clearActionHistory = exports.getActionHistory = exports.clearLastActionForReducer = exports.getLastActionForReducer = exports.getReduxAutoRefresh = exports.setReduxAutoRefresh = exports.getReduxState = exports.isReduxConnected = void 0;
|
|
17
|
+
const helpers_1 = require("../helpers");
|
|
17
18
|
let currentReduxState = null;
|
|
18
19
|
const listeners = new Set();
|
|
19
20
|
let globalReduxAutoRefresh = true;
|
|
@@ -76,7 +77,106 @@ function actionTypeOf(action) {
|
|
|
76
77
|
}
|
|
77
78
|
return 'UNKNOWN_ACTION';
|
|
78
79
|
}
|
|
79
|
-
function
|
|
80
|
+
function detectActionOrigin(stack, actionType, actionObj) {
|
|
81
|
+
const stackLower = (stack || '').toLowerCase();
|
|
82
|
+
const typeLower = (actionType || '').toLowerCase();
|
|
83
|
+
// Explicit hint on action if developer tagged it
|
|
84
|
+
if (actionObj && actionObj.__origin) {
|
|
85
|
+
const raw = String(actionObj.__origin).toLowerCase();
|
|
86
|
+
if (raw.includes('saga'))
|
|
87
|
+
return { originType: 'saga' };
|
|
88
|
+
if (raw.includes('thunk'))
|
|
89
|
+
return { originType: 'thunk' };
|
|
90
|
+
if (raw.includes('ui'))
|
|
91
|
+
return { originType: 'ui' };
|
|
92
|
+
}
|
|
93
|
+
// 1. Saga Detection (Stack + Action naming conventions)
|
|
94
|
+
const isSaga = stackLower.includes('redux-saga') ||
|
|
95
|
+
stackLower.includes('runputeffect') ||
|
|
96
|
+
stackLower.includes('proc.js') ||
|
|
97
|
+
stackLower.includes('effects.js') ||
|
|
98
|
+
stackLower.includes('sagamiddleware') ||
|
|
99
|
+
stackLower.includes('saga.ts') ||
|
|
100
|
+
stackLower.includes('saga.js') ||
|
|
101
|
+
stackLower.includes('sagas') ||
|
|
102
|
+
typeLower.includes('saga') ||
|
|
103
|
+
typeLower.startsWith('saga/') ||
|
|
104
|
+
typeLower.startsWith('@saga/');
|
|
105
|
+
// 2. Thunk / RTK Query Detection
|
|
106
|
+
const isThunk = stackLower.includes('createasyncthunk') ||
|
|
107
|
+
stackLower.includes('redux-thunk') ||
|
|
108
|
+
stackLower.includes('rtk-query') ||
|
|
109
|
+
stackLower.includes('thunkmiddleware') ||
|
|
110
|
+
stackLower.includes('actioncreator') ||
|
|
111
|
+
typeLower.includes('thunk') ||
|
|
112
|
+
typeLower.endsWith('/pending') ||
|
|
113
|
+
typeLower.endsWith('/fulfilled') ||
|
|
114
|
+
typeLower.endsWith('/rejected');
|
|
115
|
+
// 3. Parse Stack Frames to find best application caller
|
|
116
|
+
const lines = (stack || '').split('\n').map(l => l.trim()).filter(Boolean);
|
|
117
|
+
let bestFrame = null;
|
|
118
|
+
for (let i = 0; i < lines.length; i++) {
|
|
119
|
+
const line = lines[i];
|
|
120
|
+
// Ignore logger / middleware lines inside inspector
|
|
121
|
+
if (line.includes('reduxLogger') ||
|
|
122
|
+
line.includes('inspectorReduxMiddleware') ||
|
|
123
|
+
line.includes('recordAction') ||
|
|
124
|
+
line.includes('redux.js') ||
|
|
125
|
+
line.includes('redux.cjs')) {
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
const parsed = (0, helpers_1.parseStackLine)(line, false);
|
|
129
|
+
if (parsed.frameType === 'app' || (!parsed.isRuntimeNoise && parsed.fileName !== 'Unknown')) {
|
|
130
|
+
bestFrame = parsed;
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
if (!bestFrame && lines.length > 0) {
|
|
135
|
+
for (let i = 0; i < lines.length; i++) {
|
|
136
|
+
if (!lines[i].includes('reduxLogger') && !lines[i].includes('inspectorReduxMiddleware')) {
|
|
137
|
+
bestFrame = (0, helpers_1.parseStackLine)(lines[i], false);
|
|
138
|
+
break;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
let originType = 'direct';
|
|
143
|
+
if (isSaga || (bestFrame && bestFrame.fileName?.toLowerCase().includes('saga'))) {
|
|
144
|
+
originType = 'saga';
|
|
145
|
+
}
|
|
146
|
+
else if (isThunk || (bestFrame && bestFrame.fileName?.toLowerCase().includes('thunk'))) {
|
|
147
|
+
originType = 'thunk';
|
|
148
|
+
}
|
|
149
|
+
else if (bestFrame &&
|
|
150
|
+
(bestFrame.fileName?.endsWith('.tsx') ||
|
|
151
|
+
bestFrame.functionName?.includes('onPress') ||
|
|
152
|
+
bestFrame.functionName?.includes('touchable') ||
|
|
153
|
+
bestFrame.functionName?.includes('Effect'))) {
|
|
154
|
+
originType = 'ui';
|
|
155
|
+
}
|
|
156
|
+
else if (stackLower.includes('listener') || stackLower.includes('subscribe')) {
|
|
157
|
+
originType = 'listener';
|
|
158
|
+
}
|
|
159
|
+
return {
|
|
160
|
+
originType,
|
|
161
|
+
caller: bestFrame?.copyableLocation || bestFrame?.raw || undefined,
|
|
162
|
+
callerFile: bestFrame?.fullPath || bestFrame?.fileName || undefined,
|
|
163
|
+
callerLine: bestFrame?.lineNumber ? Number(bestFrame.lineNumber) : undefined,
|
|
164
|
+
callerCol: bestFrame?.columnNumber ? Number(bestFrame.columnNumber) : undefined,
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
function extractSliceName(actionType, affectedSlices) {
|
|
168
|
+
if (affectedSlices && affectedSlices.length > 0) {
|
|
169
|
+
return affectedSlices[0];
|
|
170
|
+
}
|
|
171
|
+
// If Redux Toolkit action format: e.g. "users/fetchById" -> "users"
|
|
172
|
+
const match = actionType.match(/^([a-zA-Z0-9_\-]+)\//);
|
|
173
|
+
if (match && match[1] && !match[1].startsWith('@@')) {
|
|
174
|
+
return match[1];
|
|
175
|
+
}
|
|
176
|
+
return undefined;
|
|
177
|
+
}
|
|
178
|
+
function recordAction(action, prevState, nextState, rawStack) {
|
|
179
|
+
const stack = rawStack || new Error().stack || '';
|
|
80
180
|
const type = actionTypeOf(action);
|
|
81
181
|
const payload = action && typeof action === 'object' && action.payload !== undefined
|
|
82
182
|
? action.payload
|
|
@@ -84,13 +184,26 @@ function recordAction(action, prevState, nextState) {
|
|
|
84
184
|
const now = Date.now();
|
|
85
185
|
const timestamp = new Date(now).toLocaleTimeString();
|
|
86
186
|
const affectedSlices = [];
|
|
187
|
+
const origin = detectActionOrigin(stack, type, action);
|
|
188
|
+
const sliceName = extractSliceName(type, affectedSlices);
|
|
87
189
|
if (prevState &&
|
|
88
190
|
nextState &&
|
|
89
191
|
typeof prevState === 'object' &&
|
|
90
192
|
typeof nextState === 'object') {
|
|
91
193
|
Object.keys(nextState).forEach(key => {
|
|
92
194
|
if (prevState[key] !== nextState[key]) {
|
|
93
|
-
lastActionForReducer[key] = {
|
|
195
|
+
lastActionForReducer[key] = {
|
|
196
|
+
type,
|
|
197
|
+
payload,
|
|
198
|
+
timestamp,
|
|
199
|
+
updatedAt: now,
|
|
200
|
+
originType: origin.originType,
|
|
201
|
+
callerFile: origin.callerFile,
|
|
202
|
+
callerLine: origin.callerLine,
|
|
203
|
+
callerCol: origin.callerCol,
|
|
204
|
+
caller: origin.caller,
|
|
205
|
+
stack,
|
|
206
|
+
};
|
|
94
207
|
affectedSlices.push(key);
|
|
95
208
|
}
|
|
96
209
|
});
|
|
@@ -104,6 +217,13 @@ function recordAction(action, prevState, nextState) {
|
|
|
104
217
|
affectedSlices,
|
|
105
218
|
prevState,
|
|
106
219
|
nextState,
|
|
220
|
+
stack,
|
|
221
|
+
caller: origin.caller,
|
|
222
|
+
callerFile: origin.callerFile,
|
|
223
|
+
callerLine: origin.callerLine,
|
|
224
|
+
callerCol: origin.callerCol,
|
|
225
|
+
originType: origin.originType,
|
|
226
|
+
sliceName,
|
|
107
227
|
});
|
|
108
228
|
if (actionHistory.length > MAX_HISTORY) {
|
|
109
229
|
actionHistory.length = MAX_HISTORY;
|
|
@@ -129,6 +249,7 @@ function recordAction(action, prevState, nextState) {
|
|
|
129
249
|
*/
|
|
130
250
|
const inspectorReduxMiddleware = (storeApi) => (next) => (action) => {
|
|
131
251
|
middlewareAttached = true;
|
|
252
|
+
const capturedStack = new Error().stack || '';
|
|
132
253
|
// Thunks are functions — let them run; their inner plain-action dispatches
|
|
133
254
|
// pass back through this same middleware, so nothing is lost.
|
|
134
255
|
if (typeof action === 'function') {
|
|
@@ -139,7 +260,7 @@ const inspectorReduxMiddleware = (storeApi) => (next) => (action) => {
|
|
|
139
260
|
const nextState = storeApi.getState();
|
|
140
261
|
if (currentReduxState == null)
|
|
141
262
|
currentReduxState = nextState;
|
|
142
|
-
recordAction(action, prevState, nextState);
|
|
263
|
+
recordAction(action, prevState, nextState, capturedStack);
|
|
143
264
|
return result;
|
|
144
265
|
};
|
|
145
266
|
exports.inspectorReduxMiddleware = inspectorReduxMiddleware;
|
|
@@ -162,6 +283,7 @@ const connectReduxStore = (store) => {
|
|
|
162
283
|
const originalDispatch = store.dispatch.bind(store);
|
|
163
284
|
let inWrappedDispatch = false;
|
|
164
285
|
store.dispatch = (action) => {
|
|
286
|
+
const capturedStack = new Error().stack || '';
|
|
165
287
|
if (middlewareAttached || typeof action === 'function') {
|
|
166
288
|
// Middleware handles recording, or it's a thunk whose inner dispatches
|
|
167
289
|
// will be picked up individually.
|
|
@@ -182,7 +304,7 @@ const connectReduxStore = (store) => {
|
|
|
182
304
|
finally {
|
|
183
305
|
inWrappedDispatch = false;
|
|
184
306
|
}
|
|
185
|
-
recordAction(action, prevState, store.getState());
|
|
307
|
+
recordAction(action, prevState, store.getState(), capturedStack);
|
|
186
308
|
return result;
|
|
187
309
|
};
|
|
188
310
|
(0, exports.setReduxState)(store.getState());
|
|
@@ -206,7 +328,8 @@ const connectReduxStore = (store) => {
|
|
|
206
328
|
}
|
|
207
329
|
// Change arrived outside the wrapped dispatch — record it so the
|
|
208
330
|
// timeline stays consistent, even without the original action type.
|
|
209
|
-
|
|
331
|
+
const subStack = new Error().stack || '';
|
|
332
|
+
recordAction({ type: '@@inspector/EXTERNAL_STATE_CHANGE' }, prevState, nextState, subStack);
|
|
210
333
|
});
|
|
211
334
|
};
|
|
212
335
|
exports.connectReduxStore = connectReduxStore;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { NetworkLog, RouteInfo, DiffResult, JsonContent, StackFrameType } from '../types';
|
|
2
2
|
export declare const getDomainColor: (domain: string) => string;
|
|
3
3
|
export declare const formatDateTime: (timestamp: number) => string;
|
|
4
|
+
export declare const formatTimestamp: (timestamp: number) => string;
|
|
4
5
|
export declare const getStatusColor: (status: number | null) => string;
|
|
5
6
|
export declare const getDurationColor: (duration: number | null) => string;
|
|
6
7
|
export declare const getSize: (data: unknown) => string;
|
|
@@ -44,6 +45,7 @@ export interface ParsedStackFrame {
|
|
|
44
45
|
frameType: StackFrameType | 'app' | 'dependency' | 'runtime' | 'native';
|
|
45
46
|
isUserCode: boolean;
|
|
46
47
|
isRuntimeNoise: boolean;
|
|
48
|
+
rawFilePath?: string;
|
|
47
49
|
lineNumber?: string;
|
|
48
50
|
columnNumber?: string;
|
|
49
51
|
isOrigin?: boolean;
|
|
@@ -51,6 +53,8 @@ export interface ParsedStackFrame {
|
|
|
51
53
|
}
|
|
52
54
|
/** Parses a stack trace line to extract function name, file name, extension (.tsx/.jsx/.ts), line, and column numbers */
|
|
53
55
|
export declare const parseStackLine: (rawLine: string, isOrigin?: boolean) => ParsedStackFrame;
|
|
56
|
+
/** Opens a file and line number directly in VS Code / system editor */
|
|
57
|
+
export declare const openInVSCode: (filePath: string, lineNumber?: string | number, columnNumber?: string | number) => void;
|
|
54
58
|
export declare const ANALYTICS_EVENT_PALETTE: string[];
|
|
55
59
|
export declare const getEventColor: (name: string) => string;
|
|
56
60
|
export { getEventCategory, registerGAPlugin, type GAEventCategory, type GAPlugin, } from './gaAnalyticsRegistry';
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getRuntimeDiagnostics = exports.getCategoryColors = exports.registerGAPlugin = exports.getEventCategory = exports.getEventColor = exports.ANALYTICS_EVENT_PALETTE = exports.parseStackLine = exports.getJsonPreviewText = exports.getJsonContent = exports.formatGap = exports.formatTime = exports.formatTimeShort = exports.handleOpenExternalLink = exports.getAppName = exports.getBundleIdentifier = exports.formatDateTimeToAnalytics = exports.isAllValuesEmpty = exports.getLocalizedFilePathWithSlash = exports.getLocalizedFilePath = exports.formatDisplayUrl = exports.getDiff = exports.flattenObject = exports.getNavigationInfo = exports.escapeRegex = exports.deduplicateLogs = exports.getFetchCommand = exports.getCurlCommand = exports.getBaseUrl = exports.getPath = exports.copyToClipboard = exports.getSize = exports.getDurationColor = exports.getStatusColor = exports.formatDateTime = exports.getDomainColor = void 0;
|
|
6
|
+
exports.getRuntimeDiagnostics = exports.getCategoryColors = exports.registerGAPlugin = exports.getEventCategory = exports.getEventColor = exports.ANALYTICS_EVENT_PALETTE = exports.openInVSCode = exports.parseStackLine = exports.getJsonPreviewText = exports.getJsonContent = exports.formatGap = exports.formatTime = exports.formatTimeShort = exports.handleOpenExternalLink = exports.getAppName = exports.getBundleIdentifier = exports.formatDateTimeToAnalytics = exports.isAllValuesEmpty = exports.getLocalizedFilePathWithSlash = exports.getLocalizedFilePath = exports.formatDisplayUrl = exports.getDiff = exports.flattenObject = exports.getNavigationInfo = exports.escapeRegex = exports.deduplicateLogs = exports.getFetchCommand = exports.getCurlCommand = exports.getBaseUrl = exports.getPath = exports.copyToClipboard = exports.getSize = exports.getDurationColor = exports.getStatusColor = exports.formatTimestamp = exports.formatDateTime = exports.getDomainColor = void 0;
|
|
4
7
|
const react_native_1 = require("react-native");
|
|
8
|
+
const clipboard_1 = __importDefault(require("@react-native-clipboard/clipboard"));
|
|
9
|
+
const toast_1 = require("./toast");
|
|
5
10
|
// Stylesheet
|
|
6
11
|
const AppColors_1 = require("../styles/AppColors");
|
|
7
12
|
// Constants
|
|
@@ -28,6 +33,20 @@ const formatDateTime = (timestamp) => {
|
|
|
28
33
|
return `${day}/${month}/${year} ${hours}:${minutes}:${seconds}`;
|
|
29
34
|
};
|
|
30
35
|
exports.formatDateTime = formatDateTime;
|
|
36
|
+
const formatTimestamp = (timestamp) => {
|
|
37
|
+
try {
|
|
38
|
+
const date = new Date(timestamp);
|
|
39
|
+
const hours = date.getHours().toString().padStart(2, '0');
|
|
40
|
+
const minutes = date.getMinutes().toString().padStart(2, '0');
|
|
41
|
+
const seconds = date.getSeconds().toString().padStart(2, '0');
|
|
42
|
+
const ms = date.getMilliseconds().toString().padStart(3, '0');
|
|
43
|
+
return `${hours}:${minutes}:${seconds}.${ms}`;
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return '—';
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
exports.formatTimestamp = formatTimestamp;
|
|
31
50
|
const getStatusColor = (status) => {
|
|
32
51
|
if (!status || status === 0)
|
|
33
52
|
return AppColors_1.AppColors.errorColor;
|
|
@@ -60,104 +79,43 @@ const getSize = (data) => {
|
|
|
60
79
|
}
|
|
61
80
|
};
|
|
62
81
|
exports.getSize = getSize;
|
|
63
|
-
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
const inspectorMod = react_native_1.NativeModules?.NetworkInspectorModule ||
|
|
69
|
-
(tmReg?.get ? tmReg.get('NetworkInspectorModule') : null);
|
|
70
|
-
if (inspectorMod && typeof inspectorMod.copyToClipboard === 'function') {
|
|
71
|
-
return {
|
|
72
|
-
setString: (str) => inspectorMod.copyToClipboard(str),
|
|
73
|
-
setStringAsync: (str) => inspectorMod.copyToClipboard(str),
|
|
74
|
-
};
|
|
75
|
-
}
|
|
82
|
+
const copyToClipboard = (value, label) => {
|
|
83
|
+
const resolved = typeof value === 'function' ? value() : value;
|
|
84
|
+
let textToCopy = '';
|
|
85
|
+
if (typeof resolved === 'string') {
|
|
86
|
+
textToCopy = resolved;
|
|
76
87
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
tmReg.get('NativeClipboard') ||
|
|
84
|
-
tmReg.get('ExpoClipboard');
|
|
85
|
-
if (tm &&
|
|
86
|
-
(typeof tm.setString === 'function' ||
|
|
87
|
-
typeof tm.setStringAsync === 'function')) {
|
|
88
|
-
return tm;
|
|
89
|
-
}
|
|
88
|
+
else {
|
|
89
|
+
try {
|
|
90
|
+
textToCopy = JSON.stringify(resolved, null, 2);
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
textToCopy = String(resolved);
|
|
90
94
|
}
|
|
91
95
|
}
|
|
92
|
-
|
|
93
|
-
// 3. Check legacy NativeModules table (Bridge / Old Architecture)
|
|
96
|
+
// Use @react-native-clipboard/clipboard npm package
|
|
94
97
|
try {
|
|
95
|
-
if (
|
|
96
|
-
|
|
97
|
-
return react_native_1.NativeModules.RNCClipboard;
|
|
98
|
-
}
|
|
99
|
-
if (react_native_1.NativeModules?.ExpoClipboard &&
|
|
100
|
-
typeof react_native_1.NativeModules.ExpoClipboard.setStringAsync === 'function') {
|
|
101
|
-
return react_native_1.NativeModules.ExpoClipboard;
|
|
98
|
+
if (typeof clipboard_1.default?.setString === 'function') {
|
|
99
|
+
clipboard_1.default.setString(textToCopy);
|
|
102
100
|
}
|
|
103
|
-
if (
|
|
104
|
-
|
|
105
|
-
return react_native_1.NativeModules.Clipboard;
|
|
101
|
+
else if (typeof clipboard_1.default?.default?.setString === 'function') {
|
|
102
|
+
clipboard_1.default.default.setString(textToCopy);
|
|
106
103
|
}
|
|
107
104
|
}
|
|
108
|
-
catch {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
if (react_native_1.Clipboard && typeof react_native_1.Clipboard.setString === 'function') {
|
|
112
|
-
return react_native_1.Clipboard;
|
|
105
|
+
catch (err) {
|
|
106
|
+
if (__DEV__) {
|
|
107
|
+
console.warn('[NetworkInspector] Clipboard.setString failed:', err);
|
|
113
108
|
}
|
|
114
109
|
}
|
|
115
|
-
|
|
116
|
-
return null;
|
|
117
|
-
};
|
|
118
|
-
const copyToClipboard = (value, label) => {
|
|
119
|
-
const resolved = typeof value === 'function' ? value() : value;
|
|
120
|
-
const text = typeof resolved === 'string' ? resolved : JSON.stringify(resolved, null, 2);
|
|
121
|
-
const textToCopy = text ?? '';
|
|
122
|
-
let copied = false;
|
|
110
|
+
// Trigger floating in-app bottom toast notification
|
|
123
111
|
try {
|
|
124
|
-
|
|
125
|
-
if (cb) {
|
|
126
|
-
if (typeof cb.setStringAsync === 'function') {
|
|
127
|
-
cb.setStringAsync(textToCopy);
|
|
128
|
-
copied = true;
|
|
129
|
-
}
|
|
130
|
-
else if (typeof cb.setString === 'function') {
|
|
131
|
-
cb.setString(textToCopy);
|
|
132
|
-
copied = true;
|
|
133
|
-
}
|
|
134
|
-
}
|
|
112
|
+
(0, toast_1.showToast)(label ? `${label} copied to clipboard` : 'Copied to clipboard');
|
|
135
113
|
}
|
|
136
114
|
catch { }
|
|
137
|
-
//
|
|
138
|
-
if (!copied) {
|
|
139
|
-
try {
|
|
140
|
-
const inspectorMod = react_native_1.NativeModules?.NetworkInspectorModule;
|
|
141
|
-
if (inspectorMod && typeof inspectorMod.copyToClipboard === 'function') {
|
|
142
|
-
inspectorMod.copyToClipboard(textToCopy);
|
|
143
|
-
copied = true;
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
catch { }
|
|
147
|
-
}
|
|
148
|
-
if (!copied) {
|
|
149
|
-
try {
|
|
150
|
-
if (typeof navigator !== 'undefined' && navigator?.clipboard?.writeText) {
|
|
151
|
-
navigator.clipboard.writeText(textToCopy);
|
|
152
|
-
copied = true;
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
catch { }
|
|
156
|
-
}
|
|
157
|
-
// Visual toast feedback on Android if ToastAndroid exists
|
|
115
|
+
// Native Android Toast fallback
|
|
158
116
|
try {
|
|
159
117
|
if (react_native_1.Platform.OS === 'android' && react_native_1.ToastAndroid?.show) {
|
|
160
|
-
react_native_1.ToastAndroid.show(`${label} copied
|
|
118
|
+
react_native_1.ToastAndroid.show(label ? `${label} copied to clipboard` : 'Copied to clipboard', react_native_1.ToastAndroid.SHORT);
|
|
161
119
|
}
|
|
162
120
|
}
|
|
163
121
|
catch { }
|
|
@@ -566,11 +524,16 @@ const parseStackLine = (rawLine, isOrigin = false) => {
|
|
|
566
524
|
(functionName === 'next' && isNative);
|
|
567
525
|
const isDependency = cleanPath.includes('node_modules') ||
|
|
568
526
|
cleanPath.includes('react-native/Libraries') ||
|
|
569
|
-
(cleanPath.includes('react-native-inapp-inspector') &&
|
|
527
|
+
(cleanPath.includes('react-native-inapp-inspector') &&
|
|
528
|
+
!cleanPath.includes('/example/'));
|
|
570
529
|
const isUserCode = !isNative &&
|
|
571
530
|
!isInternalBytecode &&
|
|
572
531
|
!isDependency &&
|
|
573
|
-
(fileExt === 'tsx' ||
|
|
532
|
+
(fileExt === 'tsx' ||
|
|
533
|
+
fileExt === 'jsx' ||
|
|
534
|
+
fileExt === 'ts' ||
|
|
535
|
+
fileExt === 'js' ||
|
|
536
|
+
!fileName.includes('.bundle'));
|
|
574
537
|
const frameType = isUserCode
|
|
575
538
|
? 'app'
|
|
576
539
|
: isDependency
|
|
@@ -578,7 +541,10 @@ const parseStackLine = (rawLine, isOrigin = false) => {
|
|
|
578
541
|
: isNative
|
|
579
542
|
? 'native'
|
|
580
543
|
: 'runtime';
|
|
581
|
-
const isRuntimeNoise = isInternalBytecode ||
|
|
544
|
+
const isRuntimeNoise = isInternalBytecode ||
|
|
545
|
+
isNative ||
|
|
546
|
+
functionName === 'asyncGeneratorStep' ||
|
|
547
|
+
functionName === '_next';
|
|
582
548
|
// Format clean relative project path
|
|
583
549
|
let relativePath = cleanPath;
|
|
584
550
|
if (relativePath.includes('/example/')) {
|
|
@@ -598,6 +564,7 @@ const parseStackLine = (rawLine, isOrigin = false) => {
|
|
|
598
564
|
functionName,
|
|
599
565
|
fileName,
|
|
600
566
|
fullPath: relativePath,
|
|
567
|
+
rawFilePath: fullPath,
|
|
601
568
|
fileExt,
|
|
602
569
|
frameType,
|
|
603
570
|
isUserCode,
|
|
@@ -609,6 +576,47 @@ const parseStackLine = (rawLine, isOrigin = false) => {
|
|
|
609
576
|
};
|
|
610
577
|
};
|
|
611
578
|
exports.parseStackLine = parseStackLine;
|
|
579
|
+
/** Opens a file and line number directly in VS Code / system editor */
|
|
580
|
+
const openInVSCode = (filePath, lineNumber, columnNumber) => {
|
|
581
|
+
const numLine = lineNumber ? Number(lineNumber) : 1;
|
|
582
|
+
const numCol = columnNumber ? Number(columnNumber) : 1;
|
|
583
|
+
const line = lineNumber ? `:${lineNumber}` : '';
|
|
584
|
+
const col = columnNumber ? `:${columnNumber}` : '';
|
|
585
|
+
const cleanPath = filePath.replace(/^file:\/\//, '');
|
|
586
|
+
// 1. Notify Metro dev server on host to launch editor directly on local system
|
|
587
|
+
const metroHosts = [
|
|
588
|
+
'http://localhost:8081',
|
|
589
|
+
'http://127.0.0.1:8081',
|
|
590
|
+
'http://10.0.2.2:8081',
|
|
591
|
+
];
|
|
592
|
+
metroHosts.forEach(host => {
|
|
593
|
+
try {
|
|
594
|
+
fetch(`${host}/open-stack-frame`, {
|
|
595
|
+
method: 'POST',
|
|
596
|
+
headers: { 'Content-Type': 'application/json' },
|
|
597
|
+
body: JSON.stringify({
|
|
598
|
+
file: cleanPath,
|
|
599
|
+
lineNumber: numLine,
|
|
600
|
+
column: numCol,
|
|
601
|
+
}),
|
|
602
|
+
}).catch(() => { });
|
|
603
|
+
}
|
|
604
|
+
catch { }
|
|
605
|
+
});
|
|
606
|
+
// 2. Also invoke native URL scheme handlers
|
|
607
|
+
const vscodeUrl = `vscode://file/${cleanPath.replace(/^\/+/, '')}${line}${col}`;
|
|
608
|
+
const cursorUrl = `cursor://file/${cleanPath.replace(/^\/+/, '')}${line}${col}`;
|
|
609
|
+
const vscodeInsidersUrl = `vscode-insiders://file/${cleanPath.replace(/^\/+/, '')}${line}${col}`;
|
|
610
|
+
react_native_1.Linking.openURL(vscodeUrl).catch(() => {
|
|
611
|
+
react_native_1.Linking.openURL(cursorUrl).catch(() => {
|
|
612
|
+
react_native_1.Linking.openURL(vscodeInsidersUrl).catch(() => {
|
|
613
|
+
// Fallback: Copy to clipboard so user can jump immediately
|
|
614
|
+
(0, exports.copyToClipboard)(`${cleanPath}${line}${col}`, 'Location');
|
|
615
|
+
});
|
|
616
|
+
});
|
|
617
|
+
});
|
|
618
|
+
};
|
|
619
|
+
exports.openInVSCode = openInVSCode;
|
|
612
620
|
// ─── Analytics Helpers ────────────────────────────────────────────────────────
|
|
613
621
|
exports.ANALYTICS_EVENT_PALETTE = [
|
|
614
622
|
AppColors_1.AppColors.googleBlue,
|
|
@@ -667,7 +675,11 @@ exports.getCategoryColors = getCategoryColors;
|
|
|
667
675
|
const getRuntimeDiagnostics = () => {
|
|
668
676
|
const isHermes = typeof global.HermesInternal !== 'undefined';
|
|
669
677
|
const isV8 = typeof global._v8runtime !== 'undefined';
|
|
670
|
-
const engineType = isHermes
|
|
678
|
+
const engineType = isHermes
|
|
679
|
+
? 'hermes'
|
|
680
|
+
: isV8
|
|
681
|
+
? 'v8'
|
|
682
|
+
: 'jsc';
|
|
671
683
|
const isFabric = typeof global.nativeFabricUIManager !== 'undefined' ||
|
|
672
684
|
Boolean(global.__turboModuleProxy);
|
|
673
685
|
const archType = isFabric ? 'fabric' : 'paper';
|
|
@@ -677,11 +689,14 @@ const getRuntimeDiagnostics = () => {
|
|
|
677
689
|
const hermesStats = global.HermesInternal?.getInstrumentedStats?.();
|
|
678
690
|
if (hermesStats?.js_heap_size) {
|
|
679
691
|
usedHeapMb = Number((hermesStats.js_heap_size / (1024 * 1024)).toFixed(1));
|
|
680
|
-
totalAllocMb = Number(((hermesStats.js_allocated_bytes || hermesStats.js_heap_size * 1.6) /
|
|
692
|
+
totalAllocMb = Number(((hermesStats.js_allocated_bytes || hermesStats.js_heap_size * 1.6) /
|
|
693
|
+
(1024 * 1024)).toFixed(1));
|
|
681
694
|
}
|
|
682
695
|
else if (global.performance?.memory?.usedJSHeapSize) {
|
|
683
|
-
usedHeapMb = Number((global.performance.memory.usedJSHeapSize /
|
|
684
|
-
|
|
696
|
+
usedHeapMb = Number((global.performance.memory.usedJSHeapSize /
|
|
697
|
+
(1024 * 1024)).toFixed(1));
|
|
698
|
+
totalAllocMb = Number((global.performance.memory.totalJSHeapSize /
|
|
699
|
+
(1024 * 1024)).toFixed(1));
|
|
685
700
|
}
|
|
686
701
|
}
|
|
687
702
|
catch { }
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.subscribeToast = exports.showToast = void 0;
|
|
4
|
+
const listeners = new Set();
|
|
5
|
+
const showToast = (message) => {
|
|
6
|
+
listeners.forEach(fn => {
|
|
7
|
+
try {
|
|
8
|
+
fn(message);
|
|
9
|
+
}
|
|
10
|
+
catch { }
|
|
11
|
+
});
|
|
12
|
+
};
|
|
13
|
+
exports.showToast = showToast;
|
|
14
|
+
const subscribeToast = (listener) => {
|
|
15
|
+
listeners.add(listener);
|
|
16
|
+
return () => {
|
|
17
|
+
listeners.delete(listener);
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
exports.subscribeToast = subscribeToast;
|
|
@@ -15,7 +15,10 @@
|
|
|
15
15
|
"expandAll": "Expand All",
|
|
16
16
|
"viewOnNpm": "View on NPM",
|
|
17
17
|
"later": "Later",
|
|
18
|
-
"source": "SOURCE"
|
|
18
|
+
"source": "SOURCE",
|
|
19
|
+
"open": "Open",
|
|
20
|
+
"openInBrowser": "Open in Browser",
|
|
21
|
+
"openInBrowserPrompt": "Are you sure you want to open this URL in your external browser?"
|
|
19
22
|
},
|
|
20
23
|
"header": {
|
|
21
24
|
"updateAvailableTitle": "Update Available",
|
|
@@ -279,7 +282,19 @@
|
|
|
279
282
|
"timeNow": "NOW",
|
|
280
283
|
"selectedBucket": "Bucket: {{time}} ({{count}} events)",
|
|
281
284
|
"totalRevenue": "Revenue",
|
|
282
|
-
"activeDistribution": "Category Split"
|
|
285
|
+
"activeDistribution": "Category Split",
|
|
286
|
+
"allCategory": "All",
|
|
287
|
+
"screensCategory": "Screens",
|
|
288
|
+
"overviewTab": "Overview",
|
|
289
|
+
"jsonTreeTab": "JSON Tree",
|
|
290
|
+
"rawPayloadTab": "Raw Payload",
|
|
291
|
+
"sessionContext": "Session Context",
|
|
292
|
+
"userPropertiesSnapshot": "User Properties Snapshot",
|
|
293
|
+
"parameterKeys": "Parameters ({{count}})",
|
|
294
|
+
"searchParameters": "Search parameters...",
|
|
295
|
+
"noParamsFound": "No parameters match your search",
|
|
296
|
+
"sourceFirebase": "FIREBASE GA4",
|
|
297
|
+
"sourceCustom": "CUSTOM / MANUAL"
|
|
283
298
|
},
|
|
284
299
|
"redux": {
|
|
285
300
|
"title": "Redux",
|
|
@@ -305,7 +320,38 @@
|
|
|
305
320
|
"connectionStatus": "Connected",
|
|
306
321
|
"connectionStatusNone": "Not connected",
|
|
307
322
|
"autoRefresh": "Auto-refresh",
|
|
308
|
-
"paused": "Paused"
|
|
323
|
+
"paused": "Paused",
|
|
324
|
+
"liveState": "Live State",
|
|
325
|
+
"timeline": "Timeline",
|
|
326
|
+
"persisted": "Persisted",
|
|
327
|
+
"storage": "Storage",
|
|
328
|
+
"metadata": "Metadata",
|
|
329
|
+
"inMemory": "In-Memory",
|
|
330
|
+
"slice": "SLICE",
|
|
331
|
+
"rootKeys": "Root Keys",
|
|
332
|
+
"size": "Size",
|
|
333
|
+
"actions": "actions",
|
|
334
|
+
"keys": "Keys",
|
|
335
|
+
"last": "Last",
|
|
336
|
+
"live": "Live",
|
|
337
|
+
"loading": "Loading",
|
|
338
|
+
"error": "Error",
|
|
339
|
+
"empty": "Empty",
|
|
340
|
+
"payload": "Payload",
|
|
341
|
+
"actionPayload": "Action Payload:",
|
|
342
|
+
"stateChangesDiff": "State Changes (Diff):",
|
|
343
|
+
"tapToInspectAction": "Tap to inspect action payload & diff changes",
|
|
344
|
+
"noDispatchedActions": "No dispatched actions recorded for this slice yet.",
|
|
345
|
+
"sliceJson": "Slice JSON",
|
|
346
|
+
"originSaga": "SAGA",
|
|
347
|
+
"originThunk": "THUNK",
|
|
348
|
+
"originUi": "UI",
|
|
349
|
+
"originDirect": "DIRECT",
|
|
350
|
+
"originListener": "LISTENER",
|
|
351
|
+
"triggeredFrom": "Triggered From:",
|
|
352
|
+
"openInEditor": "Open in Editor",
|
|
353
|
+
"callStack": "Call Stack Trace",
|
|
354
|
+
"sliceOrigin": "Slice / Origin"
|
|
309
355
|
},
|
|
310
356
|
"performance": {
|
|
311
357
|
"title": "Performance",
|
|
@@ -124,6 +124,9 @@ declare const LightColors: {
|
|
|
124
124
|
emerald700: string;
|
|
125
125
|
pink100: string;
|
|
126
126
|
sky100: string;
|
|
127
|
+
teal100: string;
|
|
128
|
+
teal700: string;
|
|
129
|
+
purple700: string;
|
|
127
130
|
indigo50: string;
|
|
128
131
|
gray100: string;
|
|
129
132
|
gray200: string;
|
|
@@ -279,6 +282,9 @@ export declare const getThemeColors: (isDark: boolean) => {
|
|
|
279
282
|
emerald700: string;
|
|
280
283
|
pink100: string;
|
|
281
284
|
sky100: string;
|
|
285
|
+
teal100: string;
|
|
286
|
+
teal700: string;
|
|
287
|
+
purple700: string;
|
|
282
288
|
indigo50: string;
|
|
283
289
|
gray100: string;
|
|
284
290
|
gray200: string;
|
|
@@ -133,6 +133,9 @@ const LightColors = {
|
|
|
133
133
|
emerald700: '#047857',
|
|
134
134
|
pink100: '#FCE7F3',
|
|
135
135
|
sky100: '#E0F2FE',
|
|
136
|
+
teal100: '#CCFBF1',
|
|
137
|
+
teal700: '#0F766E',
|
|
138
|
+
purple700: '#6D28D9',
|
|
136
139
|
indigo50: '#EEF2FF',
|
|
137
140
|
gray100: '#F3F4F6',
|
|
138
141
|
gray200: '#E5E7EB',
|
|
@@ -303,6 +306,9 @@ const DarkColors = {
|
|
|
303
306
|
emerald700: '#34D399',
|
|
304
307
|
pink100: '#341626',
|
|
305
308
|
sky100: '#0C2744',
|
|
309
|
+
teal100: '#134E4A',
|
|
310
|
+
teal700: '#2DD4BF',
|
|
311
|
+
purple700: '#8B5CF6',
|
|
306
312
|
indigo50: '#1E1B3A',
|
|
307
313
|
gray100: '#2A2438',
|
|
308
314
|
gray200: '#362C4E',
|