react-native-xenon 2.1.0 → 2.3.0
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 +13 -24
- package/lib/module/assets/icons/arrow-left.png +0 -0
- package/lib/module/assets/icons/beautify.png +0 -0
- package/lib/module/assets/icons/bug.png +0 -0
- package/lib/module/assets/icons/close.png +0 -0
- package/lib/module/assets/icons/delete.png +0 -0
- package/lib/module/assets/icons/hide.png +0 -0
- package/lib/module/assets/icons/move.png +0 -0
- package/lib/module/assets/icons/record.png +0 -0
- package/lib/module/assets/icons/search.png +0 -0
- package/lib/module/assets/icons/share.png +0 -0
- package/lib/module/core/constants.js +2 -0
- package/lib/module/core/constants.js.map +1 -1
- package/lib/module/core/refs.js +11 -1
- package/lib/module/core/refs.js.map +1 -1
- package/lib/module/core/utils.js +6 -1
- package/lib/module/core/utils.js.map +1 -1
- package/lib/module/hooks/useNetworkInterceptor.js +8 -3
- package/lib/module/hooks/useNetworkInterceptor.js.map +1 -1
- package/lib/module/ui/components/bubble/Bubble.js +1 -1
- package/lib/module/ui/components/bubble/Bubble.js.map +1 -1
- package/lib/module/ui/components/common/Empty.js +26 -0
- package/lib/module/ui/components/common/Empty.js.map +1 -0
- package/lib/module/ui/components/handle/Handle.js +63 -0
- package/lib/module/ui/components/handle/Handle.js.map +1 -0
- package/lib/module/ui/components/headers/DebuggerHeader.js +3 -2
- package/lib/module/ui/components/headers/DebuggerHeader.js.map +1 -1
- package/lib/module/ui/components/items/ConsolePanelItem.js +26 -12
- package/lib/module/ui/components/items/ConsolePanelItem.js.map +1 -1
- package/lib/module/ui/components/items/NetworkPanelItem.js +50 -38
- package/lib/module/ui/components/items/NetworkPanelItem.js.map +1 -1
- package/lib/module/ui/components/panels/ConsolePanel.js +15 -14
- package/lib/module/ui/components/panels/ConsolePanel.js.map +1 -1
- package/lib/module/ui/components/panels/NetworkPanel.js +13 -10
- package/lib/module/ui/components/panels/NetworkPanel.js.map +1 -1
- package/lib/module/ui/components/panels/Panel.js +25 -13
- package/lib/module/ui/components/panels/Panel.js.map +1 -1
- package/lib/module/ui/components/search-bar/SearchBar.js +5 -13
- package/lib/module/ui/components/search-bar/SearchBar.js.map +1 -1
- package/lib/typescript/src/core/constants.d.ts +2 -0
- package/lib/typescript/src/core/constants.d.ts.map +1 -1
- package/lib/typescript/src/core/refs.d.ts +2 -1
- package/lib/typescript/src/core/refs.d.ts.map +1 -1
- package/lib/typescript/src/core/utils.d.ts +2 -1
- package/lib/typescript/src/core/utils.d.ts.map +1 -1
- package/lib/typescript/src/hooks/useNetworkInterceptor.d.ts.map +1 -1
- package/lib/typescript/src/ui/components/common/Empty.d.ts +3 -0
- package/lib/typescript/src/ui/components/common/Empty.d.ts.map +1 -0
- package/lib/typescript/src/ui/components/handle/Handle.d.ts +2 -0
- package/lib/typescript/src/ui/components/handle/Handle.d.ts.map +1 -0
- package/lib/typescript/src/ui/components/headers/DebuggerHeader.d.ts.map +1 -1
- package/lib/typescript/src/ui/components/items/ConsolePanelItem.d.ts +2 -2
- package/lib/typescript/src/ui/components/items/ConsolePanelItem.d.ts.map +1 -1
- package/lib/typescript/src/ui/components/items/NetworkPanelItem.d.ts +2 -2
- package/lib/typescript/src/ui/components/items/NetworkPanelItem.d.ts.map +1 -1
- package/lib/typescript/src/ui/components/panels/ConsolePanel.d.ts.map +1 -1
- package/lib/typescript/src/ui/components/panels/NetworkPanel.d.ts.map +1 -1
- package/lib/typescript/src/ui/components/panels/Panel.d.ts.map +1 -1
- package/lib/typescript/src/ui/components/search-bar/SearchBar.d.ts.map +1 -1
- package/package.json +2 -1
- package/src/assets/icons/arrow-left.png +0 -0
- package/src/assets/icons/beautify.png +0 -0
- package/src/assets/icons/bug.png +0 -0
- package/src/assets/icons/close.png +0 -0
- package/src/assets/icons/delete.png +0 -0
- package/src/assets/icons/hide.png +0 -0
- package/src/assets/icons/move.png +0 -0
- package/src/assets/icons/record.png +0 -0
- package/src/assets/icons/search.png +0 -0
- package/src/assets/icons/share.png +0 -0
- package/src/core/constants.ts +2 -0
- package/src/core/global.d.ts +0 -26
- package/src/core/refs.ts +10 -1
- package/src/core/utils.ts +7 -1
- package/src/hooks/useNetworkInterceptor.ts +11 -5
- package/src/ui/components/bubble/Bubble.tsx +1 -1
- package/src/ui/components/common/Empty.tsx +15 -0
- package/src/ui/components/handle/Handle.tsx +60 -0
- package/src/ui/components/headers/DebuggerHeader.tsx +3 -2
- package/src/ui/components/items/ConsolePanelItem.tsx +28 -14
- package/src/ui/components/items/NetworkPanelItem.tsx +70 -57
- package/src/ui/components/panels/ConsolePanel.tsx +16 -13
- package/src/ui/components/panels/NetworkPanel.tsx +17 -8
- package/src/ui/components/panels/Panel.tsx +28 -9
- package/src/ui/components/search-bar/SearchBar.tsx +9 -13
@@ -7,6 +7,6 @@ interface NetworkPanelItemProps {
|
|
7
7
|
status?: NetworkRequest['status'];
|
8
8
|
onPress: () => void;
|
9
9
|
}
|
10
|
-
|
11
|
-
export
|
10
|
+
declare const NetworkPanelItem: import("react").NamedExoticComponent<NetworkPanelItemProps>;
|
11
|
+
export default NetworkPanelItem;
|
12
12
|
//# sourceMappingURL=NetworkPanelItem.d.ts.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"NetworkPanelItem.d.ts","sourceRoot":"","sources":["../../../../../../src/ui/components/items/NetworkPanelItem.tsx"],"names":[],"mappings":"
|
1
|
+
{"version":3,"file":"NetworkPanelItem.d.ts","sourceRoot":"","sources":["../../../../../../src/ui/components/items/NetworkPanelItem.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAIlE,UAAU,qBAAqB;IAC7B,MAAM,CAAC,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC;IAC/B,IAAI,EAAE,cAAc,CAAC,KAAK,CAAC,CAAC;IAC5B,SAAS,CAAC,EAAE,cAAc,CAAC,WAAW,CAAC,CAAC;IACxC,OAAO,CAAC,EAAE,cAAc,CAAC,SAAS,CAAC,CAAC;IACpC,MAAM,CAAC,EAAE,cAAc,CAAC,QAAQ,CAAC,CAAC;IAClC,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAsBD,QAAA,MAAM,gBAAgB,6DAqErB,CAAC;AAwCF,eAAe,gBAAgB,CAAC"}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"ConsolePanel.d.ts","sourceRoot":"","sources":["../../../../../../src/ui/components/panels/ConsolePanel.tsx"],"names":[],"mappings":"AACA,OAAO,EACL,QAAQ,
|
1
|
+
{"version":3,"file":"ConsolePanel.d.ts","sourceRoot":"","sources":["../../../../../../src/ui/components/panels/ConsolePanel.tsx"],"names":[],"mappings":"AACA,OAAO,EACL,QAAQ,EAGR,KAAK,SAAS,EACd,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AAQtB,QAAA,MAAM,YAAY;YAAkC,SAAS,CAAC,SAAS,CAAC;iDA8DtE,CAAC;AAWH,eAAe,YAAY,CAAC"}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"NetworkPanel.d.ts","sourceRoot":"","sources":["../../../../../../src/ui/components/panels/NetworkPanel.tsx"],"names":[],"mappings":"AACA,OAAO,EACL,QAAQ,EAGR,KAAK,SAAS,EACd,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;
|
1
|
+
{"version":3,"file":"NetworkPanel.d.ts","sourceRoot":"","sources":["../../../../../../src/ui/components/panels/NetworkPanel.tsx"],"names":[],"mappings":"AACA,OAAO,EACL,QAAQ,EAGR,KAAK,SAAS,EACd,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AAatB,QAAA,MAAM,YAAY;YAAkC,SAAS,CAAC,SAAS,CAAC;iDAoEtE,CAAC;AASH,eAAe,YAAY,CAAC"}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"Panel.d.ts","sourceRoot":"","sources":["../../../../../../src/ui/components/panels/Panel.tsx"],"names":[],"mappings":"AAAA,OAAO,
|
1
|
+
{"version":3,"file":"Panel.d.ts","sourceRoot":"","sources":["../../../../../../src/ui/components/panels/Panel.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAkC,IAAI,EAAE,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAgBpF,UAAU,UAAW,SAAQ,SAAS;CAAG;AAEzC,QAAA,MAAM,KAAK,6FA8CT,CAAC;AAgBH,eAAe,KAAK,CAAC"}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"SearchBar.d.ts","sourceRoot":"","sources":["../../../../../../src/ui/components/search-bar/SearchBar.tsx"],"names":[],"mappings":"AACA,OAAO,EAKL,IAAI,EAGJ,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AAUtB,UAAU,cAAe,SAAQ,SAAS;CAAG;
|
1
|
+
{"version":3,"file":"SearchBar.d.ts","sourceRoot":"","sources":["../../../../../../src/ui/components/search-bar/SearchBar.tsx"],"names":[],"mappings":"AACA,OAAO,EAKL,IAAI,EAGJ,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AAUtB,UAAU,cAAe,SAAQ,SAAS;CAAG;AAI7C,QAAA,MAAM,SAAS,iGAiEb,CAAC;AAmCH,eAAe,SAAS,CAAC"}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "react-native-xenon",
|
3
|
-
"version": "2.
|
3
|
+
"version": "2.3.0",
|
4
4
|
"description": "A powerful in-app debugging tool for React Native.",
|
5
5
|
"main": "./lib/module/index.js",
|
6
6
|
"types": "./lib/typescript/src/index.d.ts",
|
@@ -47,6 +47,7 @@
|
|
47
47
|
"xenon",
|
48
48
|
"inspector",
|
49
49
|
"debugger",
|
50
|
+
"devtools",
|
50
51
|
"https",
|
51
52
|
"network",
|
52
53
|
"nsurlsession",
|
Binary file
|
Binary file
|
package/src/assets/icons/bug.png
CHANGED
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
package/src/core/constants.ts
CHANGED
package/src/core/global.d.ts
CHANGED
@@ -1,29 +1,3 @@
|
|
1
1
|
interface XMLHttpRequest {
|
2
2
|
_interceptionId?: string;
|
3
3
|
}
|
4
|
-
|
5
|
-
declare module 'react-native/Libraries/WebSocket/NativeWebSocketModule' {
|
6
|
-
interface NativeWebSocketModule extends NativeModule {
|
7
|
-
connect(
|
8
|
-
url: string,
|
9
|
-
protocols?: string | string[],
|
10
|
-
options?: {
|
11
|
-
headers: { [headerName: string]: string };
|
12
|
-
[optionName: string]: any;
|
13
|
-
},
|
14
|
-
socketId: number,
|
15
|
-
): void;
|
16
|
-
|
17
|
-
send(data: string, socketId: number): void;
|
18
|
-
|
19
|
-
sendBinary(base64String: string, socketId: number): void;
|
20
|
-
|
21
|
-
close(code: number, reason: string, socketId: number): void;
|
22
|
-
|
23
|
-
addListener: (eventType: string) => void;
|
24
|
-
removeListeners: (count: number) => void;
|
25
|
-
}
|
26
|
-
|
27
|
-
const NativeWebSocketModule: NativeWebSocketModule;
|
28
|
-
export default NativeWebSocketModule;
|
29
|
-
}
|
package/src/core/refs.ts
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
import { createRef } from 'react';
|
2
2
|
import type { IndexedStackMethods } from '../ui/components/common/IndexedStack';
|
3
|
-
import type
|
3
|
+
import { Animated, Dimensions, type TextInput } from 'react-native';
|
4
4
|
|
5
5
|
export enum DebuggerVisibility {
|
6
6
|
Hidden = -1,
|
@@ -27,6 +27,15 @@ const refs = {
|
|
27
27
|
panel: createRef<IndexedStackMethods<PanelState>>(),
|
28
28
|
header: createRef<IndexedStackMethods<HeaderState>>(),
|
29
29
|
searchInput: createRef<TextInput>(),
|
30
|
+
panelSize: (() => {
|
31
|
+
const ref = createRef<Animated.ValueXY>();
|
32
|
+
const dimensions = Dimensions.get('window');
|
33
|
+
ref.current = new Animated.ValueXY({
|
34
|
+
x: dimensions.width,
|
35
|
+
y: Math.min(dimensions.width, dimensions.height) * 0.75,
|
36
|
+
});
|
37
|
+
return ref;
|
38
|
+
})(),
|
30
39
|
};
|
31
40
|
|
32
41
|
export default refs;
|
package/src/core/utils.ts
CHANGED
@@ -79,7 +79,7 @@ export const getConsoleTypeColor = (type: LogMessage['type']) => {
|
|
79
79
|
//#region metrics
|
80
80
|
export const getVerticalSafeMargin = (screenHeight: number) => screenHeight / 8;
|
81
81
|
|
82
|
-
export const clamp = (
|
82
|
+
export const clamp = (min: number, max: number, value: number) =>
|
83
83
|
Math.max(min, Math.min(max, value));
|
84
84
|
|
85
85
|
export const getHttpInterceptorId = () => {
|
@@ -152,6 +152,12 @@ export const convertToCurl = (
|
|
152
152
|
|
153
153
|
return curlCommand;
|
154
154
|
};
|
155
|
+
|
156
|
+
export const formatCount = (count: number) => {
|
157
|
+
if (count < 1000) return count.toString();
|
158
|
+
if (count < 1000000) return `${(count / 1000).toFixed(1)}K`;
|
159
|
+
return `${(count / 1000000).toFixed(1)}M`;
|
160
|
+
};
|
155
161
|
//#endregion
|
156
162
|
|
157
163
|
//#region decorators
|
@@ -43,14 +43,17 @@ export default function useNetworkInterceptor({
|
|
43
43
|
setNetworkRequests(initRequests);
|
44
44
|
};
|
45
45
|
|
46
|
+
const isMatchedDomain = (url: string) => {
|
47
|
+
if (!includeDomains?.length) return true;
|
48
|
+
|
49
|
+
return includeDomains.some(domain => url.includes(domain));
|
50
|
+
};
|
51
|
+
|
46
52
|
const enableHttpInterceptions = useCallback(() => {
|
47
53
|
const openCallback: HttpHandlers['open'] = (id, type, method, url) => {
|
48
54
|
if (!id) return;
|
49
55
|
|
50
|
-
|
51
|
-
!!joinedIncludeDomains.length && !includeDomains?.some(domain => url.includes(domain));
|
52
|
-
|
53
|
-
if (isNotMatchedDomain) return;
|
56
|
+
if (!isMatchedDomain(url)) return;
|
54
57
|
|
55
58
|
setNetworkRequests((draft: NetworkRequests<HttpRequest>) => {
|
56
59
|
draft.set(id, { type, method, url });
|
@@ -162,6 +165,8 @@ export default function useNetworkInterceptor({
|
|
162
165
|
) => {
|
163
166
|
if (typeof socketId !== 'number') return;
|
164
167
|
|
168
|
+
if (!isMatchedDomain(url)) return;
|
169
|
+
|
165
170
|
setNetworkRequests((draft: NetworkRequests<WebSocketRequest>) => {
|
166
171
|
draft.set(`${socketId}`, {
|
167
172
|
startTime,
|
@@ -245,7 +250,8 @@ export default function useNetworkInterceptor({
|
|
245
250
|
.set('onError', onErrorCallback)
|
246
251
|
.set('onClose', onCloseCallback)
|
247
252
|
.enableInterception();
|
248
|
-
|
253
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
254
|
+
}, [joinedIncludeDomains, setNetworkRequests]);
|
249
255
|
|
250
256
|
const enableInterception = useCallback(() => {
|
251
257
|
if (isEnabled()) return;
|
@@ -80,9 +80,9 @@ const Bubble = forwardRef<View, BubbleProps>(
|
|
80
80
|
const verticalSafeMargin = getVerticalSafeMargin(screenHeight);
|
81
81
|
|
82
82
|
const finalY = clamp(
|
83
|
-
gesture.moveY,
|
84
83
|
verticalSafeMargin,
|
85
84
|
screenHeight - verticalSafeMargin - bubbleSize,
|
85
|
+
gesture.moveY,
|
86
86
|
);
|
87
87
|
|
88
88
|
Animated.spring(pan.current, {
|
@@ -0,0 +1,15 @@
|
|
1
|
+
import type { PropsWithChildren } from 'react';
|
2
|
+
import { StyleSheet, Text, View } from 'react-native';
|
3
|
+
|
4
|
+
export default function Empty({ children }: PropsWithChildren) {
|
5
|
+
return (
|
6
|
+
<View style={styles.container}>
|
7
|
+
<Text style={styles.text}>{children}</Text>
|
8
|
+
</View>
|
9
|
+
);
|
10
|
+
}
|
11
|
+
|
12
|
+
const styles = StyleSheet.create({
|
13
|
+
container: { padding: 16, alignItems: 'center', justifyContent: 'center' },
|
14
|
+
text: { textAlign: 'center' },
|
15
|
+
});
|
@@ -0,0 +1,60 @@
|
|
1
|
+
import { useContext, useMemo, useRef } from 'react';
|
2
|
+
import { Animated, PanResponder, StyleSheet, View } from 'react-native';
|
3
|
+
import { MainContext } from '../../../contexts';
|
4
|
+
import refs from '../../../core/refs';
|
5
|
+
import { clamp } from '../../../core/utils';
|
6
|
+
import colors from '../../../theme/colors';
|
7
|
+
|
8
|
+
export default function Handle() {
|
9
|
+
const pan = useRef(new Animated.Value(0));
|
10
|
+
const {
|
11
|
+
dimensions,
|
12
|
+
debuggerState: { position },
|
13
|
+
} = useContext(MainContext)!;
|
14
|
+
|
15
|
+
const panResponder = useMemo(() => {
|
16
|
+
const minPanelHeight = dimensions.height * 0.25;
|
17
|
+
const maxPanelHeight = dimensions.height * 0.9;
|
18
|
+
|
19
|
+
return PanResponder.create({
|
20
|
+
onStartShouldSetPanResponder: () => true,
|
21
|
+
onMoveShouldSetPanResponder: () => true,
|
22
|
+
onPanResponderMove: (event, gestureState) => {
|
23
|
+
const value =
|
24
|
+
position === 'bottom' ? dimensions.height - gestureState.moveY : gestureState.moveY;
|
25
|
+
|
26
|
+
refs.panelSize.current?.setValue({
|
27
|
+
x: dimensions.width,
|
28
|
+
y: clamp(minPanelHeight, maxPanelHeight, value),
|
29
|
+
});
|
30
|
+
|
31
|
+
return Animated.event([null, { dy: pan.current }], {
|
32
|
+
useNativeDriver: false,
|
33
|
+
})(event, gestureState);
|
34
|
+
},
|
35
|
+
});
|
36
|
+
}, [dimensions.height, dimensions.width, position]);
|
37
|
+
|
38
|
+
return (
|
39
|
+
<View style={styles.handleContainer}>
|
40
|
+
<Animated.View {...panResponder.panHandlers} style={styles.handle} hitSlop={16} />
|
41
|
+
</View>
|
42
|
+
);
|
43
|
+
}
|
44
|
+
|
45
|
+
const styles = StyleSheet.create({
|
46
|
+
handleContainer: {
|
47
|
+
alignItems: 'center',
|
48
|
+
justifyContent: 'center',
|
49
|
+
backgroundColor: colors.lightGray,
|
50
|
+
borderTopColor: colors.gray,
|
51
|
+
borderTopWidth: StyleSheet.hairlineWidth,
|
52
|
+
},
|
53
|
+
handle: {
|
54
|
+
width: 48,
|
55
|
+
height: 4,
|
56
|
+
marginVertical: 8,
|
57
|
+
borderRadius: 2,
|
58
|
+
backgroundColor: colors.gray,
|
59
|
+
},
|
60
|
+
});
|
@@ -6,6 +6,7 @@ import icons from '../../../theme/icons';
|
|
6
6
|
import Divider from '../common/Divider';
|
7
7
|
import DebuggerHeaderItem from '../items/DebuggerHeaderItem';
|
8
8
|
import HeaderComponents from './HeaderComponents';
|
9
|
+
import { formatCount } from '../../../core/utils';
|
9
10
|
|
10
11
|
interface DebuggerHeaderProps {
|
11
12
|
selectedPanel: PanelState;
|
@@ -54,7 +55,7 @@ const DebuggerHeader = forwardRef<ScrollView, DebuggerHeaderProps>(
|
|
54
55
|
<DebuggerHeaderItem
|
55
56
|
isLabel
|
56
57
|
isActive={selectedPanel === PanelState.Network}
|
57
|
-
content=
|
58
|
+
content={`Network (${formatCount(networkInterceptor.networkRequests.size)})`}
|
58
59
|
onPress={() => switchTo(PanelState.Network)}
|
59
60
|
/>
|
60
61
|
|
@@ -74,7 +75,7 @@ const DebuggerHeader = forwardRef<ScrollView, DebuggerHeaderProps>(
|
|
74
75
|
<DebuggerHeaderItem
|
75
76
|
isLabel
|
76
77
|
isActive={selectedPanel === PanelState.Console}
|
77
|
-
content=
|
78
|
+
content={`Console (${formatCount(consoleInterceptor.logMessages.length)})`}
|
78
79
|
onPress={() => switchTo(PanelState.Console)}
|
79
80
|
/>
|
80
81
|
|
@@ -1,4 +1,6 @@
|
|
1
|
-
import {
|
1
|
+
import { memo } from 'react';
|
2
|
+
import { StyleSheet, Text, View } from 'react-native';
|
3
|
+
import { CONSOLE_ITEM_HEIGHT } from '../../../core/constants';
|
2
4
|
import { formatLogMessage, getConsoleTypeColor } from '../../../core/utils';
|
3
5
|
import colors from '../../../theme/colors';
|
4
6
|
import type { LogMessage } from '../../../types';
|
@@ -8,23 +10,33 @@ interface ConsolePanelItemProps extends LogMessage {
|
|
8
10
|
onPress: () => void;
|
9
11
|
}
|
10
12
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
onPress={onPress}
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
}
|
13
|
+
const ConsolePanelItem = memo<ConsolePanelItemProps>(
|
14
|
+
({ type, values, onPress }) => {
|
15
|
+
return (
|
16
|
+
<Touchable onPress={onPress} style={styles.container}>
|
17
|
+
<View style={[styles.wrapper, { backgroundColor: getConsoleTypeColor(type) }]}>
|
18
|
+
<Text numberOfLines={1} style={styles.text}>
|
19
|
+
{formatLogMessage(values)}
|
20
|
+
</Text>
|
21
|
+
</View>
|
22
|
+
</Touchable>
|
23
|
+
);
|
24
|
+
},
|
25
|
+
(prevProps, nextProps) => {
|
26
|
+
return prevProps.type === nextProps.type && prevProps.values === nextProps.values;
|
27
|
+
},
|
28
|
+
);
|
23
29
|
|
24
30
|
const styles = StyleSheet.create({
|
25
31
|
container: {
|
26
32
|
flex: 1,
|
27
|
-
|
33
|
+
paddingBottom: 4,
|
34
|
+
height: CONSOLE_ITEM_HEIGHT,
|
35
|
+
},
|
36
|
+
wrapper: {
|
37
|
+
flex: 1,
|
38
|
+
paddingHorizontal: 8,
|
39
|
+
justifyContent: 'center',
|
28
40
|
borderRadius: 8,
|
29
41
|
},
|
30
42
|
text: {
|
@@ -32,3 +44,5 @@ const styles = StyleSheet.create({
|
|
32
44
|
fontSize: 14,
|
33
45
|
},
|
34
46
|
});
|
47
|
+
|
48
|
+
export default ConsolePanelItem;
|
@@ -1,6 +1,7 @@
|
|
1
|
-
import { useMemo } from 'react';
|
1
|
+
import { memo, useMemo } from 'react';
|
2
2
|
import { StyleSheet, Text, View } from 'react-native';
|
3
3
|
import { URL } from 'react-native-url-polyfill';
|
4
|
+
import { NETWORK_ITEM_HEIGHT } from '../../../core/constants';
|
4
5
|
import {
|
5
6
|
formatRequestDuration,
|
6
7
|
formatRequestMethod,
|
@@ -8,6 +9,7 @@ import {
|
|
8
9
|
} from '../../../core/utils';
|
9
10
|
import colors from '../../../theme/colors';
|
10
11
|
import type { HttpRequest, NetworkRequest } from '../../../types';
|
12
|
+
import Divider from '../common/Divider';
|
11
13
|
import Touchable from '../common/Touchable';
|
12
14
|
|
13
15
|
interface NetworkPanelItemProps {
|
@@ -39,76 +41,85 @@ const getMethodColor = (method: string) => {
|
|
39
41
|
}
|
40
42
|
};
|
41
43
|
|
42
|
-
|
43
|
-
method,
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
}: NetworkPanelItemProps) {
|
50
|
-
const duration = formatRequestDuration(startTime, endTime);
|
51
|
-
const requestMethod = formatRequestMethod(method);
|
52
|
-
const requestStatusCode = formatRequestStatusCode(status);
|
53
|
-
const isRequestFailed = Number.isInteger(status) && status! >= 400 && status! < 600;
|
54
|
-
const textStyle = [styles.text, isRequestFailed && styles.failedText];
|
44
|
+
const NetworkPanelItem = memo<NetworkPanelItemProps>(
|
45
|
+
({ method, name, startTime, endTime, status, onPress }) => {
|
46
|
+
const duration = formatRequestDuration(startTime, endTime);
|
47
|
+
const requestMethod = formatRequestMethod(method);
|
48
|
+
const requestStatusCode = formatRequestStatusCode(status);
|
49
|
+
const isRequestFailed = Number.isInteger(status) && status! >= 400 && status! < 600;
|
50
|
+
const textStyle = [styles.text, isRequestFailed && styles.failedText];
|
55
51
|
|
56
|
-
|
57
|
-
|
52
|
+
const requestPath = useMemo(() => {
|
53
|
+
if (!name) return '[failed]';
|
58
54
|
|
59
|
-
|
60
|
-
|
61
|
-
|
55
|
+
try {
|
56
|
+
const url = new URL(name);
|
57
|
+
const suffixUrl = url.pathname + url.search;
|
62
58
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
59
|
+
if (suffixUrl === '/') return url.host;
|
60
|
+
return suffixUrl;
|
61
|
+
} catch (error) {
|
62
|
+
return name;
|
63
|
+
}
|
64
|
+
}, [name]);
|
69
65
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
66
|
+
return (
|
67
|
+
<View style={styles.container}>
|
68
|
+
<Touchable onPress={onPress} style={styles.wrapper}>
|
69
|
+
<View style={styles.column}>
|
70
|
+
<Text
|
71
|
+
numberOfLines={1}
|
72
|
+
style={[
|
73
|
+
styles.text,
|
74
|
+
styles.methodText,
|
75
|
+
{ backgroundColor: getMethodColor(requestMethod) },
|
76
|
+
]}
|
77
|
+
>
|
78
|
+
{requestMethod}
|
79
|
+
</Text>
|
80
|
+
</View>
|
84
81
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
82
|
+
<View style={[styles.column, styles.pathColumn]}>
|
83
|
+
<Text numberOfLines={1} style={textStyle}>
|
84
|
+
{requestPath}
|
85
|
+
</Text>
|
86
|
+
</View>
|
90
87
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
88
|
+
<View style={[styles.column, styles.durationColumn]}>
|
89
|
+
<Text numberOfLines={1} style={textStyle}>
|
90
|
+
{duration}
|
91
|
+
</Text>
|
92
|
+
</View>
|
96
93
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
94
|
+
<View style={styles.column}>
|
95
|
+
<Text numberOfLines={1} style={textStyle}>
|
96
|
+
{requestStatusCode}
|
97
|
+
</Text>
|
98
|
+
</View>
|
99
|
+
</Touchable>
|
100
|
+
<Divider type="horizontal" />
|
101
101
|
</View>
|
102
|
-
|
103
|
-
|
104
|
-
|
102
|
+
);
|
103
|
+
},
|
104
|
+
(prevProps, nextProps) => {
|
105
|
+
return (
|
106
|
+
prevProps.method === nextProps.method &&
|
107
|
+
prevProps.name === nextProps.name &&
|
108
|
+
prevProps.startTime === nextProps.startTime &&
|
109
|
+
prevProps.endTime === nextProps.endTime &&
|
110
|
+
prevProps.status === nextProps.status
|
111
|
+
);
|
112
|
+
},
|
113
|
+
);
|
105
114
|
|
106
115
|
const styles = StyleSheet.create({
|
107
116
|
container: {
|
108
117
|
flex: 1,
|
118
|
+
},
|
119
|
+
wrapper: {
|
109
120
|
flexDirection: 'row',
|
110
121
|
alignItems: 'center',
|
111
|
-
|
122
|
+
height: NETWORK_ITEM_HEIGHT,
|
112
123
|
columnGap: 8,
|
113
124
|
},
|
114
125
|
pathColumn: {
|
@@ -138,3 +149,5 @@ const styles = StyleSheet.create({
|
|
138
149
|
fontWeight: '600',
|
139
150
|
},
|
140
151
|
});
|
152
|
+
|
153
|
+
export default NetworkPanelItem;
|
@@ -2,18 +2,16 @@ import { forwardRef, useCallback, useContext, useMemo } from 'react';
|
|
2
2
|
import {
|
3
3
|
FlatList,
|
4
4
|
StyleSheet,
|
5
|
-
View,
|
6
5
|
type ListRenderItem,
|
7
6
|
type StyleProp,
|
8
7
|
type ViewStyle,
|
9
8
|
} from 'react-native';
|
10
9
|
import { MainContext } from '../../../contexts';
|
10
|
+
import { CONSOLE_ITEM_HEIGHT } from '../../../core/constants';
|
11
|
+
import { formatLogMessage } from '../../../core/utils';
|
11
12
|
import { DebuggerPanel, type LogMessage } from '../../../types';
|
13
|
+
import Empty from '../common/Empty';
|
12
14
|
import ConsolePanelItem from '../items/ConsolePanelItem';
|
13
|
-
import refs, { HeaderState, PanelState } from '../../../core/refs';
|
14
|
-
import { formatLogMessage } from '../../../core/utils';
|
15
|
-
|
16
|
-
const Separator = () => <View style={styles.divider} />;
|
17
15
|
|
18
16
|
const ConsolePanel = forwardRef<FlatList, { style?: StyleProp<ViewStyle> }>(({ style }, ref) => {
|
19
17
|
const {
|
@@ -41,8 +39,6 @@ const ConsolePanel = forwardRef<FlatList, { style?: StyleProp<ViewStyle> }>(({ s
|
|
41
39
|
<ConsolePanelItem
|
42
40
|
{...item}
|
43
41
|
onPress={() => {
|
44
|
-
refs.header.current?.setCurrentIndex(HeaderState.Console);
|
45
|
-
refs.panel.current?.setCurrentIndex(PanelState.ConsoleDetail);
|
46
42
|
setDebuggerState(draft => {
|
47
43
|
draft.detailsData = {
|
48
44
|
type: DebuggerPanel.Console,
|
@@ -57,16 +53,26 @@ const ConsolePanel = forwardRef<FlatList, { style?: StyleProp<ViewStyle> }>(({ s
|
|
57
53
|
[setDebuggerState],
|
58
54
|
);
|
59
55
|
|
56
|
+
const getItemLayout = useCallback(
|
57
|
+
(_: ArrayLike<LogMessage> | null | undefined, index: number) => ({
|
58
|
+
length: CONSOLE_ITEM_HEIGHT,
|
59
|
+
offset: CONSOLE_ITEM_HEIGHT * index,
|
60
|
+
index,
|
61
|
+
}),
|
62
|
+
[],
|
63
|
+
);
|
64
|
+
|
60
65
|
return (
|
61
66
|
<FlatList
|
62
67
|
ref={ref}
|
63
|
-
inverted
|
68
|
+
inverted={!!data.length}
|
64
69
|
data={data}
|
65
70
|
renderItem={renderItem}
|
66
71
|
keyExtractor={(_, index) => index.toString()}
|
67
|
-
ItemSeparatorComponent={Separator}
|
68
72
|
style={[styles.container, style]}
|
69
|
-
contentContainerStyle={styles.contentContainer}
|
73
|
+
contentContainerStyle={data.length ? styles.contentContainer : undefined}
|
74
|
+
ListEmptyComponent={<Empty>No logs yet</Empty>}
|
75
|
+
getItemLayout={getItemLayout}
|
70
76
|
/>
|
71
77
|
);
|
72
78
|
});
|
@@ -78,9 +84,6 @@ const styles = StyleSheet.create({
|
|
78
84
|
contentContainer: {
|
79
85
|
padding: 8,
|
80
86
|
},
|
81
|
-
divider: {
|
82
|
-
height: 4,
|
83
|
-
},
|
84
87
|
});
|
85
88
|
|
86
89
|
export default ConsolePanel;
|