react-native-inapp-inspector 1.1.12 → 1.1.13
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/dist/commonjs/components/AnalyticsDetail.js +64 -21
- package/dist/commonjs/components/HighlightText.js +1 -1
- package/dist/commonjs/components/JsonViewer.d.ts +3 -1
- package/dist/commonjs/components/JsonViewer.js +327 -9
- package/dist/commonjs/components/MetaAccordion.d.ts +10 -1
- package/dist/commonjs/components/MetaAccordion.js +121 -24
- package/dist/commonjs/components/NetworkIcons.d.ts +1 -0
- package/dist/commonjs/components/NetworkIcons.js +8 -1
- package/dist/commonjs/components/ReduxTreeView.d.ts +12 -3
- package/dist/commonjs/components/ReduxTreeView.js +1096 -278
- package/dist/commonjs/components/SectionHeader.d.ts +1 -1
- package/dist/commonjs/components/SectionHeader.js +7 -1
- package/dist/commonjs/constants/version.d.ts +1 -1
- package/dist/commonjs/constants/version.js +1 -1
- package/dist/commonjs/customHooks/reduxLogger.d.ts +2 -0
- package/dist/commonjs/customHooks/reduxLogger.js +2 -0
- package/dist/commonjs/helpers/index.d.ts +1 -0
- package/dist/commonjs/helpers/index.js +15 -1
- package/dist/commonjs/helpers/settingsStore.d.ts +1 -0
- package/dist/commonjs/helpers/settingsStore.js +4 -0
- package/dist/commonjs/index.js +110 -91
- package/dist/commonjs/types/index.d.ts +3 -0
- package/dist/esm/components/AnalyticsDetail.js +64 -21
- package/dist/esm/components/HighlightText.js +3 -3
- package/dist/esm/components/JsonViewer.d.ts +3 -1
- package/dist/esm/components/JsonViewer.js +295 -10
- package/dist/esm/components/MetaAccordion.d.ts +10 -1
- package/dist/esm/components/MetaAccordion.js +90 -26
- package/dist/esm/components/NetworkIcons.d.ts +1 -0
- package/dist/esm/components/NetworkIcons.js +6 -0
- package/dist/esm/components/ReduxTreeView.d.ts +12 -3
- package/dist/esm/components/ReduxTreeView.js +1095 -279
- package/dist/esm/components/SectionHeader.d.ts +1 -1
- package/dist/esm/components/SectionHeader.js +8 -2
- package/dist/esm/constants/version.d.ts +1 -1
- package/dist/esm/constants/version.js +1 -1
- package/dist/esm/customHooks/reduxLogger.d.ts +2 -0
- package/dist/esm/customHooks/reduxLogger.js +2 -0
- package/dist/esm/helpers/index.d.ts +1 -0
- package/dist/esm/helpers/index.js +14 -1
- package/dist/esm/helpers/settingsStore.d.ts +1 -0
- package/dist/esm/helpers/settingsStore.js +3 -0
- package/dist/esm/index.js +111 -92
- package/dist/esm/types/index.d.ts +3 -0
- package/package.json +1 -1
|
@@ -1,16 +1,301 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { ScrollView, View } from 'react-native';
|
|
1
|
+
import React, { useState, useEffect } from 'react';
|
|
2
|
+
import { ScrollView, View, Text, StyleSheet, Platform } from 'react-native';
|
|
3
|
+
import Svg, { Path, Rect } from 'react-native-svg';
|
|
3
4
|
// Components
|
|
4
5
|
import TreeNode from './TreeNode';
|
|
5
|
-
|
|
6
|
+
import TouchableScale from './TouchableScale';
|
|
7
|
+
// Helpers
|
|
8
|
+
import { copyToClipboard } from '../helpers';
|
|
9
|
+
// Styles
|
|
10
|
+
import { AppColors } from '../styles/AppColors';
|
|
11
|
+
import { AppFonts } from '../styles/AppFonts';
|
|
6
12
|
import styles from '../styles';
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
13
|
+
// ── Tab Icons ────────────────────────────────────────────────────────────────
|
|
14
|
+
const PrettyIcon = ({ color = '#94A3B8', size = 12 }) => (<Svg width={size} height={size} viewBox="0 0 16 16" fill="none">
|
|
15
|
+
<Path d="M5 3C3.9 3 3 3.9 3 5v1.5c0 .8-.7 1.5-1.5 1.5S0 7.3 0 6.5V5c0-2.8 2.2-5 5-5 .6 0 1 .4 1 1s-.4 1-1 1zm6 0c-1.1 0-2 .9-2 2v1.5c0 .8-.7 1.5-1.5 1.5S6 9.3 6 8.5V5c0-2.8 2.2-5 5-5 .6 0 1 .4 1 1s-.4 1-1 1z" fill={color} opacity={0.9}/>
|
|
16
|
+
<Path d="M3 11v1.5c0 .8.7 1.5 1.5 1.5S6 13.3 6 12.5V11H3zm7 0v1.5c0 .8.7 1.5 1.5 1.5S13 13.3 13 12.5V11H10z" fill={color} opacity={0.6}/>
|
|
17
|
+
</Svg>);
|
|
18
|
+
const RawIcon = ({ color = '#94A3B8', size = 12 }) => (<Svg width={size} height={size} viewBox="0 0 16 16" fill="none">
|
|
19
|
+
<Rect x="1" y="2" width="10" height="1.5" rx="0.75" fill={color} opacity={0.9}/>
|
|
20
|
+
<Rect x="1" y="5.5" width="14" height="1.5" rx="0.75" fill={color} opacity={0.6}/>
|
|
21
|
+
<Rect x="1" y="9" width="8" height="1.5" rx="0.75" fill={color} opacity={0.45}/>
|
|
22
|
+
<Rect x="1" y="12.5" width="12" height="1.5" rx="0.75" fill={color} opacity={0.3}/>
|
|
23
|
+
</Svg>);
|
|
24
|
+
const TableIcon = ({ color = '#94A3B8', size = 12 }) => (<Svg width={size} height={size} viewBox="0 0 16 16" fill="none">
|
|
25
|
+
<Rect x="1" y="1" width="14" height="14" rx="2" stroke={color} strokeWidth={1.2} opacity={0.7}/>
|
|
26
|
+
<Path d="M1 5.5h14M1 10h14M5.5 1v14M10.5 1v14" stroke={color} strokeWidth={0.8} opacity={0.5}/>
|
|
27
|
+
</Svg>);
|
|
28
|
+
// ── JsonViewer Component ─────────────────────────────────────────────────────
|
|
29
|
+
const JsonViewer = ({ data, search, forceOpen, defaultExpandDepth, wrap, fullHeight = false, onModeChange, }) => {
|
|
30
|
+
const [mode, setMode] = useState('pretty');
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
onModeChange?.(mode);
|
|
33
|
+
}, [mode, onModeChange]);
|
|
34
|
+
// Determine type and size details
|
|
35
|
+
const isObject = typeof data === 'object' && data !== null;
|
|
36
|
+
const isArray = Array.isArray(data);
|
|
37
|
+
let typeLabel = typeof data;
|
|
38
|
+
let countLabel = '';
|
|
39
|
+
if (data === null) {
|
|
40
|
+
typeLabel = 'null';
|
|
41
|
+
}
|
|
42
|
+
else if (isArray) {
|
|
43
|
+
typeLabel = 'array';
|
|
44
|
+
countLabel = `${data.length} items`;
|
|
11
45
|
}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
46
|
+
else if (isObject) {
|
|
47
|
+
typeLabel = 'object';
|
|
48
|
+
countLabel = `${Object.keys(data).length} keys`;
|
|
49
|
+
}
|
|
50
|
+
// Copy helper
|
|
51
|
+
const handleCopy = () => {
|
|
52
|
+
copyToClipboard(data, 'JSON data');
|
|
53
|
+
};
|
|
54
|
+
// Render Table view (Key-Value flat table for root keys)
|
|
55
|
+
const renderTableMode = () => {
|
|
56
|
+
if (!isObject) {
|
|
57
|
+
return (<View style={localStyles.tableRow}>
|
|
58
|
+
<Text style={localStyles.tableCellKey}>value</Text>
|
|
59
|
+
<Text style={localStyles.tableCellValue}>{String(data)}</Text>
|
|
60
|
+
</View>);
|
|
61
|
+
}
|
|
62
|
+
const keys = Object.keys(data);
|
|
63
|
+
if (keys.length === 0) {
|
|
64
|
+
return (<View style={localStyles.emptyTable}>
|
|
65
|
+
<Text style={localStyles.emptyTableText}>Empty Object</Text>
|
|
66
|
+
</View>);
|
|
67
|
+
}
|
|
68
|
+
return (<View style={localStyles.tableView}>
|
|
69
|
+
<View style={localStyles.tableHeaderRow}>
|
|
70
|
+
<Text style={[localStyles.tableHeaderCell, { flex: 2 }]}>Key</Text>
|
|
71
|
+
<Text style={[localStyles.tableHeaderCell, { flex: 3 }]}>Value</Text>
|
|
72
|
+
</View>
|
|
73
|
+
{keys.map((key) => {
|
|
74
|
+
const val = data[key];
|
|
75
|
+
let displayVal = '';
|
|
76
|
+
if (val === null) {
|
|
77
|
+
displayVal = 'null';
|
|
78
|
+
}
|
|
79
|
+
else if (val === undefined) {
|
|
80
|
+
displayVal = 'undefined';
|
|
81
|
+
}
|
|
82
|
+
else if (typeof val === 'object') {
|
|
83
|
+
displayVal = Array.isArray(val) ? `[Array(${val.length})]` : '{Object}';
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
displayVal = String(val);
|
|
87
|
+
}
|
|
88
|
+
return (<View key={key} style={localStyles.tableRow}>
|
|
89
|
+
<Text style={[localStyles.tableCellKey, { flex: 2 }]}>{key}</Text>
|
|
90
|
+
<Text style={[localStyles.tableCellValue, { flex: 3 }]} numberOfLines={2}>
|
|
91
|
+
{displayVal}
|
|
92
|
+
</Text>
|
|
93
|
+
</View>);
|
|
94
|
+
})}
|
|
95
|
+
</View>);
|
|
96
|
+
};
|
|
97
|
+
// Tree View Content
|
|
98
|
+
const tree = (<TreeNode data={data} search={search} forceOpen={forceOpen} defaultExpandDepth={defaultExpandDepth}/>);
|
|
99
|
+
return (<View style={[localStyles.container, fullHeight && { flex: 1 }]}>
|
|
100
|
+
{/* ── Top Toolbar Bar (Postman-style) ── */}
|
|
101
|
+
<View style={localStyles.toolbar}>
|
|
102
|
+
{/* Left Segmented Control */}
|
|
103
|
+
<View style={localStyles.segmentedControl}>
|
|
104
|
+
{[
|
|
105
|
+
{ key: 'pretty', label: 'Pretty', icon: PrettyIcon },
|
|
106
|
+
{ key: 'raw', label: 'Raw', icon: RawIcon },
|
|
107
|
+
{ key: 'table', label: 'Table', icon: TableIcon },
|
|
108
|
+
].map(({ key, label, icon: Icon }) => (<TouchableScale key={key} onPress={() => setMode(key)} style={[
|
|
109
|
+
localStyles.segButton,
|
|
110
|
+
mode === key && localStyles.segButtonActive,
|
|
111
|
+
]}>
|
|
112
|
+
<Icon color={mode === key ? AppColors.purple : '#94A3B8'} size={12}/>
|
|
113
|
+
<Text style={[
|
|
114
|
+
localStyles.segText,
|
|
115
|
+
mode === key && localStyles.segTextActive,
|
|
116
|
+
]}>
|
|
117
|
+
{label}
|
|
118
|
+
</Text>
|
|
119
|
+
</TouchableScale>))}
|
|
120
|
+
</View>
|
|
121
|
+
|
|
122
|
+
{/* Right Actions — badges & copy removed (caller provides header) */}
|
|
123
|
+
|
|
124
|
+
</View>
|
|
125
|
+
|
|
126
|
+
{/* ── Main View Content Area (Royal Monospace Theme) ── */}
|
|
127
|
+
<View style={[localStyles.contentWrapper, { backgroundColor: '#F8F9FB' }, fullHeight && { flex: 1, maxHeight: undefined }]}>
|
|
128
|
+
{mode === 'pretty' && (wrap ? (fullHeight ? (<ScrollView style={{ flex: 1 }} contentContainerStyle={{ flexGrow: 1 }}>
|
|
129
|
+
<View style={[styles.codeBlock, { width: '100%' }]}>{tree}</View>
|
|
130
|
+
</ScrollView>) : (<View style={[styles.codeBlock, { width: '100%' }]}>{tree}</View>)) : (fullHeight ? (<ScrollView style={{ flex: 1 }} contentContainerStyle={{ flexGrow: 1 }}>
|
|
131
|
+
<View style={styles.codeBlock}>{tree}</View>
|
|
132
|
+
</ScrollView>) : (<ScrollView horizontal showsHorizontalScrollIndicator={true} style={styles.codeBlockScroll}>
|
|
133
|
+
<View style={styles.codeBlock}>{tree}</View>
|
|
134
|
+
</ScrollView>)))}
|
|
135
|
+
|
|
136
|
+
{mode === 'raw' && (fullHeight ? (<ScrollView style={localStyles.rawScroll} contentContainerStyle={localStyles.rawContent}>
|
|
137
|
+
<Text selectable={true} style={localStyles.rawMonospaceText}>
|
|
138
|
+
{JSON.stringify(data, null, 2)}
|
|
139
|
+
</Text>
|
|
140
|
+
</ScrollView>) : (<View style={localStyles.rawContent}>
|
|
141
|
+
<Text selectable={true} style={localStyles.rawMonospaceText}>
|
|
142
|
+
{JSON.stringify(data, null, 2)}
|
|
143
|
+
</Text>
|
|
144
|
+
</View>))}
|
|
145
|
+
|
|
146
|
+
{mode === 'table' && (fullHeight ? (<ScrollView style={localStyles.rawScroll}>
|
|
147
|
+
{renderTableMode()}
|
|
148
|
+
</ScrollView>) : (<View style={localStyles.rawScroll}>
|
|
149
|
+
{renderTableMode()}
|
|
150
|
+
</View>))}
|
|
151
|
+
</View>
|
|
152
|
+
</View>);
|
|
15
153
|
};
|
|
154
|
+
const localStyles = StyleSheet.create({
|
|
155
|
+
container: {
|
|
156
|
+
backgroundColor: '#FFFFFF',
|
|
157
|
+
borderRadius: 12,
|
|
158
|
+
borderWidth: 1.5,
|
|
159
|
+
borderColor: '#E2E8F0',
|
|
160
|
+
overflow: 'hidden',
|
|
161
|
+
shadowColor: '#000',
|
|
162
|
+
shadowOpacity: 0.04,
|
|
163
|
+
shadowRadius: 5,
|
|
164
|
+
shadowOffset: { width: 0, height: 2 },
|
|
165
|
+
elevation: 2,
|
|
166
|
+
width: '100%',
|
|
167
|
+
},
|
|
168
|
+
toolbar: {
|
|
169
|
+
flexDirection: 'row',
|
|
170
|
+
alignItems: 'center',
|
|
171
|
+
justifyContent: 'space-between',
|
|
172
|
+
backgroundColor: '#F8FAFC',
|
|
173
|
+
borderBottomWidth: 1,
|
|
174
|
+
borderBottomColor: '#E2E8F0',
|
|
175
|
+
paddingHorizontal: 12,
|
|
176
|
+
paddingVertical: 8,
|
|
177
|
+
},
|
|
178
|
+
segmentedControl: {
|
|
179
|
+
flexDirection: 'row',
|
|
180
|
+
backgroundColor: '#E2E8F0',
|
|
181
|
+
borderRadius: 8,
|
|
182
|
+
padding: 2,
|
|
183
|
+
},
|
|
184
|
+
segButton: {
|
|
185
|
+
flexDirection: 'row',
|
|
186
|
+
alignItems: 'center',
|
|
187
|
+
gap: 4,
|
|
188
|
+
paddingHorizontal: 10,
|
|
189
|
+
paddingVertical: 5,
|
|
190
|
+
borderRadius: 6,
|
|
191
|
+
},
|
|
192
|
+
segButtonActive: {
|
|
193
|
+
backgroundColor: '#FFFFFF',
|
|
194
|
+
shadowColor: '#000',
|
|
195
|
+
shadowOpacity: 0.08,
|
|
196
|
+
shadowRadius: 2,
|
|
197
|
+
shadowOffset: { width: 0, height: 1 },
|
|
198
|
+
elevation: 1,
|
|
199
|
+
},
|
|
200
|
+
segText: {
|
|
201
|
+
fontFamily: AppFonts.interBold,
|
|
202
|
+
fontSize: 9.5,
|
|
203
|
+
color: '#64748B',
|
|
204
|
+
letterSpacing: 0.3,
|
|
205
|
+
},
|
|
206
|
+
segTextActive: {
|
|
207
|
+
color: AppColors.purple,
|
|
208
|
+
},
|
|
209
|
+
rightActions: {
|
|
210
|
+
flexDirection: 'row',
|
|
211
|
+
alignItems: 'center',
|
|
212
|
+
gap: 6,
|
|
213
|
+
},
|
|
214
|
+
badge: {
|
|
215
|
+
backgroundColor: 'rgba(104,75,155,0.06)',
|
|
216
|
+
borderWidth: 1,
|
|
217
|
+
borderColor: 'rgba(104,75,155,0.15)',
|
|
218
|
+
borderRadius: 5,
|
|
219
|
+
paddingHorizontal: 6,
|
|
220
|
+
paddingVertical: 2.5,
|
|
221
|
+
},
|
|
222
|
+
badgeText: {
|
|
223
|
+
fontFamily: AppFonts.interBold,
|
|
224
|
+
fontSize: 9,
|
|
225
|
+
color: AppColors.purple,
|
|
226
|
+
},
|
|
227
|
+
copyButton: {
|
|
228
|
+
width: 24,
|
|
229
|
+
height: 24,
|
|
230
|
+
borderRadius: 6,
|
|
231
|
+
backgroundColor: 'rgba(104,75,155,0.08)',
|
|
232
|
+
alignItems: 'center',
|
|
233
|
+
justifyContent: 'center',
|
|
234
|
+
},
|
|
235
|
+
contentWrapper: {
|
|
236
|
+
backgroundColor: '#FFFFFF',
|
|
237
|
+
minHeight: 120,
|
|
238
|
+
maxHeight: 480,
|
|
239
|
+
},
|
|
240
|
+
rawScroll: {
|
|
241
|
+
flex: 1,
|
|
242
|
+
backgroundColor: '#FAF9F6', // Royal off-white paper tone
|
|
243
|
+
},
|
|
244
|
+
rawContent: {
|
|
245
|
+
padding: 12,
|
|
246
|
+
},
|
|
247
|
+
rawMonospaceText: {
|
|
248
|
+
fontFamily: Platform.OS === 'ios' ? 'Courier New' : 'monospace',
|
|
249
|
+
fontSize: 11.5,
|
|
250
|
+
color: '#0F172A',
|
|
251
|
+
lineHeight: 16,
|
|
252
|
+
},
|
|
253
|
+
tableView: {
|
|
254
|
+
flex: 1,
|
|
255
|
+
},
|
|
256
|
+
tableHeaderRow: {
|
|
257
|
+
flexDirection: 'row',
|
|
258
|
+
backgroundColor: '#F1F5F9',
|
|
259
|
+
borderBottomWidth: 1,
|
|
260
|
+
borderBottomColor: '#E2E8F0',
|
|
261
|
+
paddingVertical: 8,
|
|
262
|
+
paddingHorizontal: 12,
|
|
263
|
+
},
|
|
264
|
+
tableHeaderCell: {
|
|
265
|
+
fontFamily: AppFonts.interBold,
|
|
266
|
+
fontSize: 9.5,
|
|
267
|
+
color: '#475569',
|
|
268
|
+
letterSpacing: 0.5,
|
|
269
|
+
textTransform: 'uppercase',
|
|
270
|
+
},
|
|
271
|
+
tableRow: {
|
|
272
|
+
flexDirection: 'row',
|
|
273
|
+
borderBottomWidth: 1,
|
|
274
|
+
borderBottomColor: '#F1F5F9',
|
|
275
|
+
paddingVertical: 10,
|
|
276
|
+
paddingHorizontal: 12,
|
|
277
|
+
alignItems: 'center',
|
|
278
|
+
},
|
|
279
|
+
tableCellKey: {
|
|
280
|
+
fontFamily: Platform.OS === 'ios' ? 'Courier-Bold' : 'monospace',
|
|
281
|
+
fontSize: 11.5,
|
|
282
|
+
fontWeight: 'bold',
|
|
283
|
+
color: '#0F172A',
|
|
284
|
+
},
|
|
285
|
+
tableCellValue: {
|
|
286
|
+
fontFamily: Platform.OS === 'ios' ? 'Courier' : 'monospace',
|
|
287
|
+
fontSize: 11.5,
|
|
288
|
+
color: '#475569',
|
|
289
|
+
},
|
|
290
|
+
emptyTable: {
|
|
291
|
+
padding: 24,
|
|
292
|
+
alignItems: 'center',
|
|
293
|
+
justifyContent: 'center',
|
|
294
|
+
},
|
|
295
|
+
emptyTableText: {
|
|
296
|
+
fontFamily: AppFonts.interMedium,
|
|
297
|
+
fontSize: 12,
|
|
298
|
+
color: '#94A3B8',
|
|
299
|
+
},
|
|
300
|
+
});
|
|
16
301
|
export default JsonViewer;
|
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
|
|
2
|
+
export interface MetaAccordionProps {
|
|
3
|
+
status: number | null | undefined;
|
|
4
|
+
statusColor: string;
|
|
5
|
+
duration: number | null | undefined;
|
|
6
|
+
size: string;
|
|
7
|
+
triggeredAt: string;
|
|
8
|
+
method: string;
|
|
9
|
+
contentType?: string;
|
|
10
|
+
url: string;
|
|
11
|
+
}
|
|
3
12
|
declare const MetaAccordion: ({ status, statusColor, duration, size, triggeredAt, method, contentType, url, }: MetaAccordionProps) => React.JSX.Element;
|
|
4
13
|
export default MetaAccordion;
|
|
@@ -1,20 +1,59 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { View, Pressable, Text, Animated
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import { View, Pressable, Text, Animated } from 'react-native';
|
|
3
3
|
// Constants
|
|
4
4
|
import { DURATION_FAST_MS, DURATION_SLOW_MS } from '../constants';
|
|
5
5
|
// Custom Hooks
|
|
6
6
|
import useAccordion from '../customHooks/useAccordion';
|
|
7
7
|
// Helpers
|
|
8
|
-
import { getDurationColor } from '../helpers';
|
|
8
|
+
import { getDurationColor, handleOpenExternalLink } from '../helpers';
|
|
9
9
|
// Assets
|
|
10
10
|
import { ChevronIcon, CalendarIcon, StatusIcon, ClockIcon, SizeIcon, TerminalIcon, GlobeIcon, } from './NetworkIcons';
|
|
11
|
+
// Components
|
|
12
|
+
import TouchableScale from './TouchableScale';
|
|
11
13
|
// Stylesheet
|
|
12
14
|
import { AppColors } from '../styles/AppColors';
|
|
13
|
-
import styles from '../styles';
|
|
14
15
|
import { AppFonts } from '../styles/AppFonts';
|
|
16
|
+
import styles from '../styles';
|
|
15
17
|
const MetaAccordion = ({ status, statusColor, duration, size, triggeredAt, method, contentType, url, }) => {
|
|
18
|
+
const [urlExpanded, setUrlExpanded] = useState(false);
|
|
16
19
|
const { toggleOpen, chevronStyle, bodyStyle } = useAccordion(true, 400, 390);
|
|
17
20
|
const isFailed = status === 0 || status == null;
|
|
21
|
+
const renderFormattedUrl = (rawUrl) => {
|
|
22
|
+
if (!rawUrl)
|
|
23
|
+
return '—';
|
|
24
|
+
try {
|
|
25
|
+
const doubleSlashIndex = rawUrl.indexOf('//');
|
|
26
|
+
let temp = rawUrl;
|
|
27
|
+
let protocol = '';
|
|
28
|
+
if (doubleSlashIndex !== -1) {
|
|
29
|
+
protocol = rawUrl.substring(0, doubleSlashIndex + 2);
|
|
30
|
+
temp = rawUrl.substring(doubleSlashIndex + 2);
|
|
31
|
+
}
|
|
32
|
+
const slashIndex = temp.indexOf('/');
|
|
33
|
+
let host = temp;
|
|
34
|
+
let pathAndSearch = '';
|
|
35
|
+
if (slashIndex !== -1) {
|
|
36
|
+
host = temp.substring(0, slashIndex);
|
|
37
|
+
pathAndSearch = temp.substring(slashIndex);
|
|
38
|
+
}
|
|
39
|
+
const queryIndex = pathAndSearch.indexOf('?');
|
|
40
|
+
let pathname = pathAndSearch;
|
|
41
|
+
let search = '';
|
|
42
|
+
if (queryIndex !== -1) {
|
|
43
|
+
pathname = pathAndSearch.substring(0, queryIndex);
|
|
44
|
+
search = pathAndSearch.substring(queryIndex);
|
|
45
|
+
}
|
|
46
|
+
return (<Text style={{ lineHeight: 16 }}>
|
|
47
|
+
{protocol ? (<Text style={{ color: '#94A3B8', fontFamily: AppFonts.interRegular }}>{protocol}</Text>) : null}
|
|
48
|
+
<Text style={{ color: AppColors.purple, fontFamily: AppFonts.interBold }}>{host}</Text>
|
|
49
|
+
<Text style={{ color: '#334155', fontFamily: AppFonts.interMedium }}>{pathname}</Text>
|
|
50
|
+
{search ? (<Text style={{ color: '#0D9488', fontFamily: AppFonts.interRegular }}>{search}</Text>) : null}
|
|
51
|
+
</Text>);
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
return rawUrl;
|
|
55
|
+
}
|
|
56
|
+
};
|
|
18
57
|
return (<View style={styles.metaContainer}>
|
|
19
58
|
<Pressable onPress={toggleOpen} hitSlop={12}>
|
|
20
59
|
<View style={styles.metaHeader}>
|
|
@@ -140,29 +179,54 @@ const MetaAccordion = ({ status, statusColor, duration, size, triggeredAt, metho
|
|
|
140
179
|
</View>
|
|
141
180
|
<View style={styles.metaDivider}/>
|
|
142
181
|
|
|
143
|
-
<View style={[styles.metaRow, { alignItems: 'flex-start' }]}>
|
|
144
|
-
<View style={
|
|
145
|
-
<
|
|
146
|
-
|
|
182
|
+
<View style={[styles.metaRow, { alignItems: 'flex-start', flexDirection: 'column', gap: 6 }]}>
|
|
183
|
+
<View style={{ flexDirection: 'row', justifyContent: 'space-between', width: '100%', alignItems: 'center' }}>
|
|
184
|
+
<View style={styles.metaLabelRow}>
|
|
185
|
+
<GlobeIcon color={AppColors.grayTextWeak} size={14}/>
|
|
186
|
+
<Text style={styles.metaLabel}>Full URL</Text>
|
|
187
|
+
</View>
|
|
188
|
+
|
|
189
|
+
<View style={{ flexDirection: 'row', alignItems: 'center', gap: 10 }}>
|
|
190
|
+
{url && url.length > 50 && (<TouchableScale onPress={() => setUrlExpanded(prev => !prev)} hitSlop={8}>
|
|
191
|
+
<Text style={{
|
|
192
|
+
fontFamily: AppFonts.interBold,
|
|
193
|
+
fontSize: 10.5,
|
|
194
|
+
color: AppColors.purple,
|
|
195
|
+
}}>
|
|
196
|
+
{urlExpanded ? 'Show Less' : 'Show More'}
|
|
197
|
+
</Text>
|
|
198
|
+
</TouchableScale>)}
|
|
199
|
+
|
|
200
|
+
{url && (<TouchableScale onPress={() => handleOpenExternalLink(url)} hitSlop={8}>
|
|
201
|
+
<Text style={{
|
|
202
|
+
fontFamily: AppFonts.interBold,
|
|
203
|
+
fontSize: 10.5,
|
|
204
|
+
color: AppColors.purple,
|
|
205
|
+
textDecorationLine: 'underline',
|
|
206
|
+
}}>
|
|
207
|
+
Open
|
|
208
|
+
</Text>
|
|
209
|
+
</TouchableScale>)}
|
|
210
|
+
</View>
|
|
211
|
+
</View>
|
|
212
|
+
|
|
213
|
+
<View style={{
|
|
214
|
+
backgroundColor: '#F8FAFC',
|
|
215
|
+
borderRadius: 8,
|
|
216
|
+
padding: 8,
|
|
217
|
+
borderWidth: 1.5,
|
|
218
|
+
borderColor: '#E2E8F0',
|
|
219
|
+
width: '100%',
|
|
220
|
+
marginTop: 2,
|
|
221
|
+
}}>
|
|
222
|
+
<Text selectable={true} numberOfLines={urlExpanded ? undefined : 2} ellipsizeMode="tail" style={{
|
|
223
|
+
fontSize: 11,
|
|
224
|
+
textAlign: 'left',
|
|
225
|
+
lineHeight: 16.5,
|
|
226
|
+
}}>
|
|
227
|
+
{renderFormattedUrl(url)}
|
|
228
|
+
</Text>
|
|
147
229
|
</View>
|
|
148
|
-
<Text selectable={true} numberOfLines={3} ellipsizeMode="tail" onPress={() => {
|
|
149
|
-
if (url) {
|
|
150
|
-
Linking.openURL(url).catch(() => { });
|
|
151
|
-
}
|
|
152
|
-
}} style={[
|
|
153
|
-
styles.metaValue,
|
|
154
|
-
{
|
|
155
|
-
fontSize: 11.5,
|
|
156
|
-
color: url ? AppColors.purple : AppColors.grayTextWeak,
|
|
157
|
-
textDecorationLine: url ? 'underline' : 'none',
|
|
158
|
-
fontFamily: AppFonts.interMedium,
|
|
159
|
-
flex: 1,
|
|
160
|
-
textAlign: 'right',
|
|
161
|
-
lineHeight: 16,
|
|
162
|
-
},
|
|
163
|
-
]}>
|
|
164
|
-
{url || '—'}
|
|
165
|
-
</Text>
|
|
166
230
|
</View>
|
|
167
231
|
</View>
|
|
168
232
|
</Animated.View>
|
|
@@ -50,3 +50,4 @@ export declare const WarningTriangleIcon: ({ color, size, }: any) => React.JSX.E
|
|
|
50
50
|
export declare const ErrorCircleIcon: ({ color, size, }: any) => React.JSX.Element;
|
|
51
51
|
export declare const TrendingUpIcon: ({ color, size, }: any) => React.JSX.Element;
|
|
52
52
|
export declare const MotionIcon: ({ color, size, }: any) => React.JSX.Element;
|
|
53
|
+
export declare const SortIcon: ({ ascending, color, size, }: any) => React.JSX.Element;
|
|
@@ -302,3 +302,9 @@ export const MotionIcon = ({ color = AppColors.grayTextWeak, size = 14, }) => {
|
|
|
302
302
|
<Path d="M5 3l14 9-14 9V3z" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
|
|
303
303
|
</Svg>);
|
|
304
304
|
};
|
|
305
|
+
export const SortIcon = ({ ascending, color = AppColors.purple, size = 14, }) => {
|
|
306
|
+
return (<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
|
|
307
|
+
<Path d="M12 4l-6 6h12z" fill={ascending ? color : AppColors.grayTextWeak}/>
|
|
308
|
+
<Path d="M12 20l6-6H6z" fill={!ascending ? color : AppColors.grayTextWeak}/>
|
|
309
|
+
</Svg>);
|
|
310
|
+
};
|
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
export declare const
|
|
3
|
-
export declare const ReduxTreeView: ({ state, lastActionMap, search, }: {
|
|
2
|
+
export declare const ReduxTreeView: ({ state, actionHistory, lastActionMap, search, onSearchChange, autoRefresh, onToggleAutoRefresh, onClearHistory, onDetailOpenChange, selectedSliceKey, onSelectSliceKey, selectedActionId, onSelectActionId, }: {
|
|
4
3
|
state: any;
|
|
5
|
-
|
|
4
|
+
actionHistory?: any[];
|
|
5
|
+
lastActionMap?: Record<string, any>;
|
|
6
6
|
search?: string;
|
|
7
|
+
onSearchChange?: (val: string) => void;
|
|
8
|
+
autoRefresh?: boolean;
|
|
9
|
+
onToggleAutoRefresh?: () => void;
|
|
10
|
+
onClearHistory?: () => void;
|
|
11
|
+
onDetailOpenChange?: (isOpen: boolean) => void;
|
|
12
|
+
selectedSliceKey?: string | null;
|
|
13
|
+
onSelectSliceKey?: (key: string | null) => void;
|
|
14
|
+
selectedActionId?: number | null;
|
|
15
|
+
onSelectActionId?: (id: number | null) => void;
|
|
7
16
|
}) => React.JSX.Element;
|