frontend: fix double SafeAreaView edges
Tabs already have a SafeAreaView navigation insets, so the ScreenLayout adds it two times
Parents:
bcb065f1 file(s) changed
- frontend/components/ui/ScreenLayout.tsx +34 -43
frontend/components/ui/ScreenLayout.tsx
1 -
import React from 'react';
1 +
import React from "react";
2 2
3 3
import {
4 4
View,
5 5
ScrollView,
6 6
StyleSheet,
7 7
Image,
8 8
Pressable,
9 9
StatusBar,
10 -
} from 'react-native';
10 +
} from "react-native";
11 11
12 -
import { SafeAreaView } from 'react-native-safe-area-context';
13 -
import { IconSymbol } from '@/components/ui/icon-symbol';
14 -
import { useThemeColor } from '@/hooks/use-theme-color';
15 -
import { Typography, Spacing, BorderRadius } from '@/constants/theme'
16 -
import { ThemedText } from '@/components/misc/themed-text'
12 +
import { SafeAreaView } from "react-native-safe-area-context";
13 +
import { IconSymbol } from "@/components/ui/icon-symbol";
14 +
import { useThemeColor } from "@/hooks/use-theme-color";
15 +
import { Typography, Spacing, BorderRadius } from "@/constants/theme";
16 +
import { ThemedText } from "@/components/misc/themed-text";
17 17
18 18
interface ScreenLayoutProps {
19 19
children: React.ReactNode;
20 20
userName?: string;
21 21
userAvatar?: string;
▸ 2 unchanged lines
24 24
scrollEnabled?: boolean;
25 25
}
26 26
27 27
export const ScreenLayout: React.FC<ScreenLayoutProps> = ({
28 28
children,
29 -
userName = 'Usuário',
29 +
userName = "Usuário",
30 30
userAvatar,
31 31
onNotificationPress,
32 32
showNotificationBadge = false,
33 33
scrollEnabled = true,
34 34
}) => {
35 -
const textColor = useThemeColor({}, 'text');
36 -
const backgroundColor = useThemeColor({}, 'background');
37 -
const surfaceColor = useThemeColor({}, 'surface');
38 -
const dividerColor = useThemeColor({}, 'divider');
39 -
const accentBlue = useThemeColor({}, 'accentBlue');
40 -
const tintColor = useThemeColor({}, 'tint');
35 +
const textColor = useThemeColor({}, "text");
36 +
const backgroundColor = useThemeColor({}, "background");
37 +
const surfaceColor = useThemeColor({}, "surface");
38 +
const dividerColor = useThemeColor({}, "divider");
39 +
const accentBlue = useThemeColor({}, "accentBlue");
40 +
const tintColor = useThemeColor({}, "tint");
41 41
42 42
const styles = StyleSheet.create({
43 43
container: {
44 44
flex: 1,
45 45
backgroundColor: backgroundColor,
▸ 6 unchanged lines
52 52
paddingHorizontal: Spacing.containerPadding,
53 53
paddingVertical: 12,
54 54
backgroundColor: surfaceColor,
55 55
borderBottomWidth: 1,
56 56
borderBottomColor: dividerColor,
57 -
flexDirection: 'row',
58 -
justifyContent: 'space-between',
59 -
alignItems: 'center',
57 +
flexDirection: "row",
58 +
justifyContent: "space-between",
59 +
alignItems: "center",
60 60
},
61 61
headerLeft: {
62 -
flexDirection: 'row',
63 -
alignItems: 'center',
62 +
flexDirection: "row",
63 +
alignItems: "center",
64 64
gap: Spacing.inlineGapSm,
65 65
},
66 66
avatar: {
67 67
width: 40,
68 68
height: 40,
69 69
borderRadius: 20,
70 70
backgroundColor: accentBlue,
71 71
},
72 72
userName: {
73 73
fontSize: Typography.bodyLg.fontSize,
74 -
fontWeight: '600',
74 +
fontWeight: "600",
75 75
color: textColor,
76 76
},
77 77
notificationButton: {
78 78
width: 40,
79 79
height: 40,
80 80
borderRadius: BorderRadius.md,
81 -
justifyContent: 'center',
82 -
alignItems: 'center',
81 +
justifyContent: "center",
82 +
alignItems: "center",
83 83
activeOpacity: 0.7,
84 84
},
85 85
notificationBadge: {
86 -
position: 'absolute',
86 +
position: "absolute",
87 87
top: 4,
88 88
right: 4,
89 89
width: 8,
90 90
height: 8,
91 91
borderRadius: 4,
▸ 2 unchanged lines
94 94
scrollContent: {
95 95
paddingHorizontal: Spacing.containerPadding,
96 96
paddingVertical: Spacing.sectionGap,
97 97
},
98 98
});
99 -
99 +
100 100
return (
101 101
<View style={styles.container}>
102 -
<StatusBar
103 -
barStyle="dark-content"
104 -
backgroundColor={surfaceColor}
105 -
/>
106 -
<SafeAreaView style={styles.safeAreaView}>
102 +
<StatusBar barStyle="dark-content" backgroundColor={surfaceColor} />
103 +
<SafeAreaView
104 +
style={styles.safeAreaView}
105 +
edges={["top", "left", "right"]}
106 +
>
107 107
<View style={styles.header}>
108 108
<View style={styles.headerLeft}>
109 109
{userAvatar ? (
110 -
<Image
111 -
source={{ uri: userAvatar }}
112 -
style={styles.avatar}
113 -
/>
110 +
<Image source={{ uri: userAvatar }} style={styles.avatar} />
114 111
) : (
115 112
<View style={styles.avatar} />
116 113
)}
117 114
<View>
118 -
<ThemedText style={styles.userName}>
119 -
Olá, {userName}
120 -
</ThemedText>
115 +
<ThemedText style={styles.userName}>Olá, {userName}</ThemedText>
121 116
</View>
122 117
</View>
123 118
124 119
<Pressable
125 120
style={styles.notificationButton}
▸ 4 unchanged lines
130 125
style={{
131 126
fontSize: 24,
132 127
color: textColor,
133 128
}}
134 129
>
135 -
<IconSymbol size={24} name="notifications" color={textColor} />
130 +
<IconSymbol size={24} name="notifications" color={textColor} />
136 131
</View>
137 -
{showNotificationBadge && (
138 -
<View style={styles.notificationBadge} />
139 -
)}
132 +
{showNotificationBadge && <View style={styles.notificationBadge} />}
140 133
</Pressable>
141 134
</View>
142 135
143 136
<ScrollView
144 137
scrollEnabled={scrollEnabled}
145 138
showsVerticalScrollIndicator={false}
146 139
contentContainerStyle={scrollEnabled ? undefined : { flex: 1 }}
147 140
scrollEventThrottle={16}
148 141
>
149 -
<View style={styles.scrollContent}>
150 -
{children}
151 -
</View>
142 +
<View style={styles.scrollContent}>{children}</View>
152 143
</ScrollView>
153 144
</SafeAreaView>
154 145
</View>
155 146
);
156 147
};
157 148
158 149
export default ScreenLayout;