Skip to content

Commit 11a9c63

Browse files
committed
feat: redesign UI with new design system and security improvements
- Add inline SVG icon system with optional react-native-svg dependency - Update color palette with dark theme as default and light mode toggle - Redesign NetworkLoggerOverlay with new header, search, and filter UI - Redesign NetworkLogItem with alternating rows and collapsible sections - Update FloatingButton and NonFloatingButton with new badge design - Update ExportModal to match new design system - Mask sensitive data in cURL commands and header displays - Remove API filter from filter bar
1 parent dfa7cb3 commit 11a9c63

11 files changed

Lines changed: 1743 additions & 659 deletions

File tree

src/CopyItem.tsx

Lines changed: 41 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,26 @@
11
import React, { useState, useCallback, useRef, useEffect } from 'react';
22
import {
33
Alert,
4+
StyleSheet,
5+
Text,
46
TouchableOpacity,
7+
View,
58
type StyleProp,
69
type ViewStyle,
710
} from 'react-native';
8-
import Icon from './Icon';
11+
import { SvgIcon } from './SvgIcon';
12+
import { colors } from './constants/colors';
913

1014
let Clipboard: any = null;
1115
try {
1216
Clipboard = require('@react-native-clipboard/clipboard').default;
13-
} catch (error) {
17+
} catch {
1418
Clipboard = null;
1519
}
1620

1721
interface CopyItemProps {
1822
textToCopy: string;
23+
size?: number;
1924
checkDuration?: number;
2025
style?: StyleProp<ViewStyle>;
2126
useCopyToClipboard?: boolean;
@@ -25,15 +30,16 @@ export const CopyItem: React.FC<CopyItemProps> = ({
2530
textToCopy,
2631
checkDuration = 2000,
2732
style,
33+
size = 16,
2834
useCopyToClipboard,
2935
}) => {
3036
const [copied, setCopied] = useState(false);
3137
const timeoutRef = useRef<NodeJS.Timeout | null>(null);
3238

3339
useEffect(() => {
3440
if (useCopyToClipboard && !Clipboard) {
35-
throw new Error(
36-
'Copy to clipboard functionality is required (useCopyToClipboard=true) but @react-native-clipboard/clipboard module is not installed. Please install it with: npm install @react-native-clipboard/clipboard'
41+
console.warn(
42+
'[NetworkLogger] Copy to clipboard enabled but @react-native-clipboard/clipboard is not installed. Install it with: npm install @react-native-clipboard/clipboard'
3743
);
3844
}
3945
}, [useCopyToClipboard]);
@@ -57,23 +63,49 @@ export const CopyItem: React.FC<CopyItemProps> = ({
5763
}, [textToCopy, checkDuration, useCopyToClipboard]);
5864

5965
if (!useCopyToClipboard) {
60-
return null;
66+
return (
67+
<View style={[style, styles.disabledContainer]}>
68+
<Text style={styles.disabledText}>Copy not enabled</Text>
69+
</View>
70+
);
6171
}
6272

6373
if (!Clipboard) {
64-
return null;
74+
return (
75+
<View style={[style, styles.disabledContainer]}>
76+
<Text style={styles.disabledText}>Clipboard unavailable</Text>
77+
</View>
78+
);
6579
}
6680

6781
return (
6882
<TouchableOpacity
69-
style={style}
83+
style={[styles.button, style]}
7084
onPress={handleCopy}
71-
activeOpacity={0.5}
85+
activeOpacity={0.7}
7286
accessibilityRole="button"
7387
accessibilityLabel={copied ? 'Copied to clipboard' : 'Copy to clipboard'}
7488
disabled={!useCopyToClipboard}
7589
>
76-
{copied ? <Icon type="done" /> : <Icon type="copy" />}
90+
{copied ? (
91+
<SvgIcon name="check" size={size} color={colors.success} />
92+
) : (
93+
<SvgIcon name="copy" size={size} color="#94A3B8" />
94+
)}
7795
</TouchableOpacity>
7896
);
7997
};
98+
99+
const styles = StyleSheet.create({
100+
button: {
101+
padding: 4,
102+
},
103+
disabledContainer: {
104+
opacity: 0.6,
105+
},
106+
disabledText: {
107+
fontSize: 10,
108+
color: '#64748B',
109+
fontStyle: 'italic',
110+
},
111+
});

src/FloatingButton.tsx

Lines changed: 91 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@ import {
66
Dimensions,
77
} from 'react-native';
88
import React, { useEffect } from 'react';
9-
import Icon from './Icon';
9+
import { SvgIcon } from './SvgIcon';
1010
import NonFloatingButton from './NonFloatingButton';
11-
import { colors } from './constants/colors';
11+
import { colors, getThemeColors, type ThemeMode } from './constants/colors';
12+
1213
const { width: screenWidth, height: screenHeight } = Dimensions.get('window');
1314

1415
let Animated: any = null;
@@ -45,7 +46,6 @@ try {
4546
}
4647

4748
const BUTTON_SIZE = 58;
48-
const CLOSE_BUTTON_SIZE = 58;
4949
const PADDING = 20;
5050

5151
interface FloatingButtonProps {
@@ -55,6 +55,7 @@ interface FloatingButtonProps {
5555
errorCount?: number;
5656
draggable?: boolean;
5757
enableDeviceShake?: boolean;
58+
theme?: ThemeMode;
5859
}
5960

6061
const AnimatedFloatingButton: React.FC<FloatingButtonProps> = ({
@@ -63,7 +64,9 @@ const AnimatedFloatingButton: React.FC<FloatingButtonProps> = ({
6364
logsLength,
6465
errorCount = 0,
6566
enableDeviceShake,
67+
theme = 'dark',
6668
}) => {
69+
const themeColors = getThemeColors(theme);
6770
const positionX = useSharedValue(screenWidth - BUTTON_SIZE - PADDING);
6871
const positionY = useSharedValue(screenHeight - 150);
6972
const startPositionX = useSharedValue(0);
@@ -76,7 +79,7 @@ const AnimatedFloatingButton: React.FC<FloatingButtonProps> = ({
7679
startPositionX.value = positionX.value;
7780
startPositionY.value = positionY.value;
7881
})
79-
.onUpdate((event: { translationX: any; translationY: any }) => {
82+
.onUpdate((event: { translationX: number; translationY: number }) => {
8083
const newX = startPositionX.value + event.translationX;
8184
const newY = startPositionY.value + event.translationY;
8285

@@ -121,7 +124,7 @@ const AnimatedFloatingButton: React.FC<FloatingButtonProps> = ({
121124
{enableDeviceShake && (
122125
<Animated.View style={[styles.floatingCloseIcon, animatedCloseStyle]}>
123126
<TouchableOpacity onPress={hideIcon} style={styles.closeButton}>
124-
<Icon type="close" />
127+
<SvgIcon name="x" size={16} color={themeColors.textMuted} />
125128
</TouchableOpacity>
126129
</Animated.View>
127130
)}
@@ -130,16 +133,52 @@ const AnimatedFloatingButton: React.FC<FloatingButtonProps> = ({
130133
<TouchableOpacity
131134
onPress={openModal}
132135
activeOpacity={0.9}
133-
style={styles.buttonTouchable}
136+
style={[
137+
styles.buttonTouchable,
138+
{
139+
backgroundColor: themeColors.surfaceContainer,
140+
borderColor: themeColors.border,
141+
},
142+
]}
134143
>
135-
<Text style={styles.floatingButtonText}>📊 {logsLength}</Text>
136-
{errorCount > 0 && (
144+
<SvgIcon name="barChart" size={16} color={themeColors.text} />
145+
<Text
146+
style={[styles.floatingButtonText, { color: themeColors.text }]}
147+
>
148+
{logsLength}
149+
</Text>
150+
{errorCount > 0 ? (
137151
<View style={styles.errorBadge}>
138152
<Text style={styles.errorBadgeText}>
139153
{errorCount > 99 ? '99+' : errorCount}
140154
</Text>
141155
</View>
156+
) : (
157+
<View style={styles.successBadge}>
158+
<SvgIcon name="check" size={10} color="#0F172A" />
159+
</View>
142160
)}
161+
{/* Drag handle */}
162+
<View style={styles.dragHandle}>
163+
<View
164+
style={[
165+
styles.dragDot,
166+
{ backgroundColor: themeColors.textMuted },
167+
]}
168+
/>
169+
<View
170+
style={[
171+
styles.dragDot,
172+
{ backgroundColor: themeColors.textMuted },
173+
]}
174+
/>
175+
<View
176+
style={[
177+
styles.dragDot,
178+
{ backgroundColor: themeColors.textMuted },
179+
]}
180+
/>
181+
</View>
143182
</TouchableOpacity>
144183
</Animated.View>
145184
</GestureDetector>
@@ -166,15 +205,6 @@ const FloatingButton: React.FC<FloatingButtonProps> = (props) => {
166205
};
167206

168207
const styles = StyleSheet.create({
169-
gestureRoot: {
170-
flex: 1,
171-
top: 0,
172-
left: 0,
173-
right: 0,
174-
bottom: 0,
175-
position: 'absolute',
176-
pointerEvents: 'box-none',
177-
},
178208
container: {
179209
flex: 1,
180210
top: 0,
@@ -188,61 +218,71 @@ const styles = StyleSheet.create({
188218
position: 'absolute',
189219
zIndex: 1000,
190220
},
191-
staticPosition: {
192-
left: screenWidth - BUTTON_SIZE - PADDING,
193-
top: screenHeight - 150,
194-
},
195221
buttonTouchable: {
196-
backgroundColor: '#007AFF',
197-
padding: 16,
198-
borderRadius: 25,
199-
elevation: 5,
200-
shadowOffset: { width: 0, height: 2 },
201-
shadowOpacity: 0.3,
202-
shadowRadius: 4,
203-
justifyContent: 'center',
222+
flexDirection: 'row',
204223
alignItems: 'center',
224+
gap: 8,
225+
paddingVertical: 10,
226+
paddingHorizontal: 14,
227+
borderWidth: 1,
228+
elevation: 4,
229+
shadowColor: '#000',
230+
shadowOffset: { width: 0, height: 4 },
231+
shadowOpacity: 0.3,
232+
shadowRadius: 8,
205233
},
206234
floatingCloseIcon: {
207235
position: 'absolute',
208236
zIndex: 1001,
209237
},
210-
staticClosePosition: {
211-
left: screenWidth - BUTTON_SIZE - PADDING + 4,
212-
top: screenHeight - 150 - 50,
213-
},
214238
closeButton: {
215-
padding: 16,
216-
borderRadius: 70,
217-
width: CLOSE_BUTTON_SIZE,
218-
height: CLOSE_BUTTON_SIZE,
219-
justifyContent: 'center',
220-
alignItems: 'center',
221-
fontWeight: '900',
239+
padding: 8,
222240
},
223241
floatingButtonText: {
224-
color: 'white',
225-
fontSize: 14,
226-
fontWeight: 'bold',
242+
fontSize: 13,
243+
fontWeight: '600',
227244
},
228245
errorBadge: {
229246
position: 'absolute',
230-
top: -4,
231-
right: -4,
247+
top: -6,
248+
right: -6,
232249
backgroundColor: colors.error,
233-
borderRadius: 10,
234-
minWidth: 20,
235-
height: 20,
250+
minWidth: 18,
251+
height: 18,
236252
justifyContent: 'center',
237253
alignItems: 'center',
238254
paddingHorizontal: 4,
255+
borderRadius: 9,
239256
borderWidth: 2,
240-
borderColor: '#fff',
257+
borderColor: '#10131a',
241258
},
242259
errorBadgeText: {
243260
color: '#fff',
244-
fontSize: 10,
245-
fontWeight: 'bold',
261+
fontSize: 9,
262+
fontWeight: '700',
263+
},
264+
successBadge: {
265+
position: 'absolute',
266+
top: -6,
267+
right: -6,
268+
backgroundColor: colors.success,
269+
width: 18,
270+
height: 18,
271+
justifyContent: 'center',
272+
alignItems: 'center',
273+
borderRadius: 9,
274+
borderWidth: 2,
275+
borderColor: '#10131a',
276+
},
277+
dragHandle: {
278+
marginLeft: 4,
279+
opacity: 0.3,
280+
gap: 2,
281+
},
282+
dragDot: {
283+
width: 3,
284+
height: 3,
285+
borderRadius: 1.5,
246286
},
247287
});
248288

0 commit comments

Comments
 (0)