react-native-network-lens 0.1.0 → 0.2.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 +254 -97
- package/lib/module/components/BodyViewer.js +31 -19
- package/lib/module/components/BodyViewer.js.map +1 -1
- package/lib/module/components/JsonTree/JsonTreeView.js +10 -6
- package/lib/module/components/JsonTree/JsonTreeView.js.map +1 -1
- package/lib/module/components/JsonTree/model.js +2 -0
- package/lib/module/components/JsonTree/model.js.map +1 -1
- package/lib/module/components/NetworkLens.js +4 -8
- package/lib/module/components/NetworkLens.js.map +1 -1
- package/lib/module/components/NetworkLensOverlay.js +67 -22
- package/lib/module/components/NetworkLensOverlay.js.map +1 -1
- package/lib/module/components/RawTextView.js +10 -6
- package/lib/module/components/RawTextView.js.map +1 -1
- package/lib/module/components/RequestDetails/RequestDetails.js +44 -21
- package/lib/module/components/RequestDetails/RequestDetails.js.map +1 -1
- package/lib/module/components/RequestList/FilterBar.js +3 -3
- package/lib/module/components/RequestList/FilterBar.js.map +1 -1
- package/lib/module/components/RequestList/RequestList.js +7 -8
- package/lib/module/components/RequestList/RequestList.js.map +1 -1
- package/lib/module/components/ui/Button.js +21 -5
- package/lib/module/components/ui/Button.js.map +1 -1
- package/lib/module/components/ui/Pill.js +13 -6
- package/lib/module/components/ui/Pill.js.map +1 -1
- package/lib/module/settings.js +48 -0
- package/lib/module/settings.js.map +1 -0
- package/lib/module/theme.js +4 -4
- package/lib/typescript/src/components/BodyViewer.d.ts.map +1 -1
- package/lib/typescript/src/components/JsonTree/JsonTreeView.d.ts.map +1 -1
- package/lib/typescript/src/components/JsonTree/model.d.ts.map +1 -1
- package/lib/typescript/src/components/NetworkLens.d.ts +0 -3
- package/lib/typescript/src/components/NetworkLens.d.ts.map +1 -1
- package/lib/typescript/src/components/NetworkLensOverlay.d.ts +1 -1
- package/lib/typescript/src/components/NetworkLensOverlay.d.ts.map +1 -1
- package/lib/typescript/src/components/RawTextView.d.ts.map +1 -1
- package/lib/typescript/src/components/RequestDetails/RequestDetails.d.ts.map +1 -1
- package/lib/typescript/src/components/RequestList/RequestList.d.ts +1 -4
- package/lib/typescript/src/components/RequestList/RequestList.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Button.d.ts +3 -1
- package/lib/typescript/src/components/ui/Button.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Pill.d.ts +1 -0
- package/lib/typescript/src/components/ui/Pill.d.ts.map +1 -1
- package/lib/typescript/src/settings.d.ts +18 -0
- package/lib/typescript/src/settings.d.ts.map +1 -0
- package/package.json +3 -3
- package/src/components/BodyViewer.tsx +37 -19
- package/src/components/JsonTree/JsonTreeView.tsx +11 -5
- package/src/components/JsonTree/model.ts +2 -0
- package/src/components/NetworkLens.tsx +2 -11
- package/src/components/NetworkLensOverlay.tsx +54 -23
- package/src/components/RawTextView.tsx +11 -6
- package/src/components/RequestDetails/RequestDetails.tsx +31 -19
- package/src/components/RequestList/FilterBar.tsx +2 -2
- package/src/components/RequestList/RequestList.tsx +3 -7
- package/src/components/ui/Button.tsx +23 -7
- package/src/components/ui/Pill.tsx +14 -5
- package/src/settings.ts +55 -0
- package/src/theme.ts +2 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useCallback, useMemo, useState
|
|
1
|
+
import { useCallback, useMemo, useState } from 'react';
|
|
2
2
|
import { FlatList, Share, StyleSheet, Text, View } from 'react-native';
|
|
3
3
|
import type NetworkRequest from '../../core/NetworkRequest';
|
|
4
4
|
import { useTheme } from '../../theme';
|
|
@@ -30,8 +30,6 @@ interface Props {
|
|
|
30
30
|
loggingEnabled: boolean;
|
|
31
31
|
onPressItem: (id: string) => void;
|
|
32
32
|
menuActions: ActionItem[];
|
|
33
|
-
/** Optional row rendered above the search bar (used by the overlay for title + close). */
|
|
34
|
-
header?: ReactNode;
|
|
35
33
|
}
|
|
36
34
|
|
|
37
35
|
const keyExtractor = (row: NetworkRequestRow) => row.id;
|
|
@@ -52,7 +50,6 @@ const RequestList = ({
|
|
|
52
50
|
loggingEnabled,
|
|
53
51
|
onPressItem,
|
|
54
52
|
menuActions,
|
|
55
|
-
header,
|
|
56
53
|
}: Props) => {
|
|
57
54
|
const theme = useTheme();
|
|
58
55
|
const [search, setSearch] = useState('');
|
|
@@ -134,7 +131,6 @@ const RequestList = ({
|
|
|
134
131
|
},
|
|
135
132
|
]}
|
|
136
133
|
>
|
|
137
|
-
{header}
|
|
138
134
|
<View style={styles.searchRow}>
|
|
139
135
|
<SearchInput
|
|
140
136
|
value={search}
|
|
@@ -215,8 +211,8 @@ const styles = StyleSheet.create({
|
|
|
215
211
|
paddingVertical: 8,
|
|
216
212
|
borderBottomWidth: StyleSheet.hairlineWidth,
|
|
217
213
|
},
|
|
218
|
-
searchRow: { flexDirection: 'row', alignItems: 'center'
|
|
219
|
-
search: { flex: 1 },
|
|
214
|
+
searchRow: { flexDirection: 'row', alignItems: 'center' },
|
|
215
|
+
search: { flex: 1, marginRight: 4 },
|
|
220
216
|
statusBar: { paddingHorizontal: 12, paddingVertical: 4 },
|
|
221
217
|
statusText: { fontSize: 11, fontWeight: '600' },
|
|
222
218
|
statusTextPaused: { color: '#ffffff' },
|
|
@@ -8,11 +8,17 @@ import {
|
|
|
8
8
|
} from 'react-native';
|
|
9
9
|
import { useTheme } from '../../theme';
|
|
10
10
|
|
|
11
|
+
// Object form keeps compatibility with React Native versions before numeric hitSlop.
|
|
12
|
+
const HIT_SLOP_SMALL = { top: 6, bottom: 6, left: 6, right: 6 };
|
|
13
|
+
const HIT_SLOP = { top: 8, bottom: 8, left: 8, right: 8 };
|
|
14
|
+
|
|
11
15
|
interface TextButtonProps {
|
|
12
16
|
label: string;
|
|
13
17
|
onPress?: () => void;
|
|
14
18
|
disabled?: boolean;
|
|
15
19
|
active?: boolean;
|
|
20
|
+
/** Text-only button in the primary colour, for navigation actions like Back. */
|
|
21
|
+
plain?: boolean;
|
|
16
22
|
style?: StyleProp<ViewStyle>;
|
|
17
23
|
textStyle?: StyleProp<TextStyle>;
|
|
18
24
|
}
|
|
@@ -22,6 +28,7 @@ export const TextButton = ({
|
|
|
22
28
|
onPress,
|
|
23
29
|
disabled,
|
|
24
30
|
active,
|
|
31
|
+
plain,
|
|
25
32
|
style,
|
|
26
33
|
textStyle,
|
|
27
34
|
}: TextButtonProps) => {
|
|
@@ -31,13 +38,15 @@ export const TextButton = ({
|
|
|
31
38
|
accessibilityRole="button"
|
|
32
39
|
disabled={disabled}
|
|
33
40
|
onPress={onPress}
|
|
34
|
-
hitSlop={
|
|
41
|
+
hitSlop={HIT_SLOP_SMALL}
|
|
35
42
|
style={({ pressed }) => [
|
|
36
43
|
styles.button,
|
|
37
44
|
{
|
|
38
|
-
backgroundColor:
|
|
39
|
-
?
|
|
40
|
-
:
|
|
45
|
+
backgroundColor: plain
|
|
46
|
+
? 'transparent'
|
|
47
|
+
: active
|
|
48
|
+
? theme.colors.primary
|
|
49
|
+
: theme.colors.surfaceAlt,
|
|
41
50
|
},
|
|
42
51
|
disabled ? styles.disabled : pressed && styles.pressed,
|
|
43
52
|
style,
|
|
@@ -46,7 +55,13 @@ export const TextButton = ({
|
|
|
46
55
|
<Text
|
|
47
56
|
style={[
|
|
48
57
|
styles.label,
|
|
49
|
-
{
|
|
58
|
+
{
|
|
59
|
+
color: plain
|
|
60
|
+
? theme.colors.primary
|
|
61
|
+
: active
|
|
62
|
+
? theme.colors.onPrimary
|
|
63
|
+
: theme.colors.text,
|
|
64
|
+
},
|
|
50
65
|
textStyle,
|
|
51
66
|
]}
|
|
52
67
|
>
|
|
@@ -79,7 +94,7 @@ export const IconButton = ({
|
|
|
79
94
|
accessibilityLabel={accessibilityLabel}
|
|
80
95
|
disabled={disabled}
|
|
81
96
|
onPress={onPress}
|
|
82
|
-
hitSlop={
|
|
97
|
+
hitSlop={HIT_SLOP}
|
|
83
98
|
style={({ pressed }) => [
|
|
84
99
|
styles.icon,
|
|
85
100
|
active && { backgroundColor: theme.colors.primary },
|
|
@@ -108,7 +123,8 @@ const styles = StyleSheet.create({
|
|
|
108
123
|
},
|
|
109
124
|
label: { fontSize: 13, fontWeight: '600' },
|
|
110
125
|
icon: {
|
|
111
|
-
|
|
126
|
+
minWidth: 32,
|
|
127
|
+
paddingHorizontal: 6,
|
|
112
128
|
height: 32,
|
|
113
129
|
borderRadius: 8,
|
|
114
130
|
alignItems: 'center',
|
|
@@ -14,6 +14,7 @@ interface Props {
|
|
|
14
14
|
style?: StyleProp<ViewStyle>;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
+
/** Fixed-height badge so filled and outlined variants align on one row. */
|
|
17
18
|
export const Pill = ({ label, color, filled, small, style }: Props) => (
|
|
18
19
|
<View
|
|
19
20
|
style={[
|
|
@@ -39,15 +40,23 @@ export const Pill = ({ label, color, filled, small, style }: Props) => (
|
|
|
39
40
|
|
|
40
41
|
const styles = StyleSheet.create({
|
|
41
42
|
pill: {
|
|
43
|
+
height: 24,
|
|
44
|
+
minWidth: 44,
|
|
45
|
+
paddingHorizontal: 8,
|
|
42
46
|
borderWidth: 1,
|
|
43
47
|
borderRadius: 6,
|
|
44
|
-
|
|
45
|
-
|
|
48
|
+
alignItems: 'center',
|
|
49
|
+
justifyContent: 'center',
|
|
46
50
|
alignSelf: 'flex-start',
|
|
47
51
|
},
|
|
48
|
-
pillSmall: {
|
|
52
|
+
pillSmall: {
|
|
53
|
+
height: 20,
|
|
54
|
+
minWidth: 40,
|
|
55
|
+
paddingHorizontal: 6,
|
|
56
|
+
borderRadius: 5,
|
|
57
|
+
},
|
|
49
58
|
outline: { backgroundColor: 'transparent' },
|
|
50
|
-
text: { fontSize: 12, fontWeight: '700', letterSpacing: 0.3 },
|
|
51
|
-
textSmall: { fontSize: 11 },
|
|
59
|
+
text: { fontSize: 12, lineHeight: 14, fontWeight: '700', letterSpacing: 0.3 },
|
|
60
|
+
textSmall: { fontSize: 11, lineHeight: 13 },
|
|
52
61
|
textFilled: { color: '#ffffff' },
|
|
53
62
|
});
|
package/src/settings.ts
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { useSyncExternalStore } from 'react';
|
|
2
|
+
import type { Theme } from './theme';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Tiny in-memory preferences shared by every viewer in the session, e.g. the
|
|
6
|
+
* code font scale the user picks with the "Aa" button.
|
|
7
|
+
*/
|
|
8
|
+
export type CodeFontScale = 'small' | 'medium' | 'large';
|
|
9
|
+
|
|
10
|
+
const SCALE_FACTOR: Record<CodeFontScale, number> = {
|
|
11
|
+
small: 0.85,
|
|
12
|
+
medium: 1,
|
|
13
|
+
large: 1.2,
|
|
14
|
+
};
|
|
15
|
+
const ORDER: CodeFontScale[] = ['small', 'medium', 'large'];
|
|
16
|
+
|
|
17
|
+
let scale: CodeFontScale = 'medium';
|
|
18
|
+
const listeners = new Set<() => void>();
|
|
19
|
+
|
|
20
|
+
const subscribe = (listener: () => void) => {
|
|
21
|
+
listeners.add(listener);
|
|
22
|
+
return () => {
|
|
23
|
+
listeners.delete(listener);
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
const getScale = () => scale;
|
|
27
|
+
|
|
28
|
+
export const setCodeFontScale = (next: CodeFontScale) => {
|
|
29
|
+
if (scale === next) return;
|
|
30
|
+
scale = next;
|
|
31
|
+
listeners.forEach((listener) => listener());
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export const cycleCodeFontScale = () => {
|
|
35
|
+
setCodeFontScale(
|
|
36
|
+
ORDER[(ORDER.indexOf(scale) + 1) % ORDER.length] ?? 'medium'
|
|
37
|
+
);
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export const useCodeFontScale = (): CodeFontScale =>
|
|
41
|
+
useSyncExternalStore(subscribe, getScale, getScale);
|
|
42
|
+
|
|
43
|
+
/** Font metrics for code views: the theme's base size times the chosen scale. */
|
|
44
|
+
export const useCodeFont = (theme: Theme) => {
|
|
45
|
+
const current = useCodeFontScale();
|
|
46
|
+
const factor = SCALE_FACTOR[current];
|
|
47
|
+
const fontSize = Math.round(theme.sizes.codeFontSize * factor);
|
|
48
|
+
return {
|
|
49
|
+
scale: current,
|
|
50
|
+
fontSize,
|
|
51
|
+
lineHeight: Math.round(fontSize * 1.5),
|
|
52
|
+
/** Average glyph advance for monospace fonts; used to size horizontal scroll areas. */
|
|
53
|
+
charWidth: fontSize * 0.62,
|
|
54
|
+
};
|
|
55
|
+
};
|
package/src/theme.ts
CHANGED
|
@@ -80,7 +80,7 @@ export const lightTheme: Theme = {
|
|
|
80
80
|
onHighlight: '#1f2937',
|
|
81
81
|
},
|
|
82
82
|
fonts: { mono: mono ?? 'monospace' },
|
|
83
|
-
sizes: { codeFontSize:
|
|
83
|
+
sizes: { codeFontSize: 14, codeLineHeight: 21 },
|
|
84
84
|
};
|
|
85
85
|
|
|
86
86
|
export const darkTheme: Theme = {
|
|
@@ -114,7 +114,7 @@ export const darkTheme: Theme = {
|
|
|
114
114
|
onHighlight: '#fef3c7',
|
|
115
115
|
},
|
|
116
116
|
fonts: { mono: mono ?? 'monospace' },
|
|
117
|
-
sizes: { codeFontSize:
|
|
117
|
+
sizes: { codeFontSize: 14, codeLineHeight: 21 },
|
|
118
118
|
};
|
|
119
119
|
|
|
120
120
|
export type ThemeInput = ThemeName | DeepPartial<Theme>;
|