@@ -13,11 +13,11 @@ import {
1313 StatusBar ,
1414 StyleSheet ,
1515 TouchableOpacity ,
16- View
16+ View ,
17+ Platform
1718} from 'react-native' ;
1819import Cancel from '../assets/icons/x-circle.svg' ;
1920
20- // Context for page title metadata
2121export const PageTitleContext = createContext < {
2222 customSuffix ?: string ;
2323 setPageTitleInfo : ( info : { customSuffix ?: string } ) => void ;
@@ -49,7 +49,7 @@ export default function Layout() {
4949}
5050
5151function InnerLayout ( ) {
52- const { isDarkMode, isLoading } = useDarkMode ( ) ; // Add isLoading if available
52+ const { isDarkMode, isLoading } = useDarkMode ( ) ;
5353 const [ fontsLoaded ] = useFonts ( {
5454 InterRegular : require ( '@/assets/fonts/Inter/static/Inter_18pt-Thin.ttf' ) ,
5555 } ) ;
@@ -60,76 +60,65 @@ function InnerLayout() {
6060 const [ refreshing , setRefreshing ] = useState ( false ) ;
6161 const { customSuffix } = usePageTitleContext ( ) ;
6262
63+ const theme = {
64+ backgroundColor : isDarkMode ? 'rgba(42, 42, 42, 1)' : '#F8FAFC' ,
65+ contentBackground : isDarkMode ? 'rgba(42, 42, 42, 0.8)' : '#F8FAFC' ,
66+ pageBackground : isDarkMode ? 'rgba(42, 42, 42, 1)' : '#fff' ,
67+ sidebarBackground : isDarkMode ? 'rgba(42, 42, 42, 1)' : '#fff' ,
68+ closeButtonBackground : isDarkMode ? 'rgba(42, 42, 42, 0.8)' : '#fff' ,
69+ closeButtonTouchBackground : isDarkMode ? 'rgba(42, 42, 42, 1)' : '#fff' ,
70+ iconFill : isDarkMode ? '#fff' : '#000' ,
71+ } ;
72+
73+ // FIX: Safari background color sync
74+ useEffect ( ( ) => {
75+ if ( Platform . OS === 'web' && typeof document !== 'undefined' ) {
76+ document . body . style . backgroundColor = theme . backgroundColor ;
77+ document . documentElement . style . backgroundColor = theme . backgroundColor ;
78+
79+ // Update meta theme-color for Safari mobile address bar
80+ const metaTheme = document . querySelector ( 'meta[name="theme-color"]' ) ;
81+ if ( metaTheme ) {
82+ metaTheme . setAttribute ( 'content' , theme . backgroundColor ) ;
83+ }
84+ }
85+ } , [ isDarkMode , theme . backgroundColor ] ) ;
86+
6387 const routeLabels : Record < string , string > = {
64- index : 'Home' ,
65- age : 'AGE' ,
66- intothedeep : 'DIVE' ,
67- energize : 'ENERGIZE' ,
68- forward : 'FORWARD' ,
69- gameChangers : 'GAMECHANGERS' ,
70- inshow : 'INSHOW' ,
71- rise : 'RISE' ,
72- discord : 'Discord' ,
73- app : 'App' ,
74- ScoutSheet : 'ScoutSheet' ,
75- tranks : 'Teams' ,
76- tauto : 'Auto' ,
77- ttele : 'TeleOp' ,
78- tendgame : 'Endgame' ,
79- mranks : 'Matches' ,
80- qual : 'Qualifiers' ,
81- finals : 'Finals' ,
82- premier : 'Premier' ,
83- tac : 'Terms & Conditions' ,
84- privacy : 'Privacy Policy' ,
85- systemstatus : 'Systems Status' ,
88+ index : 'Home' , age : 'AGE' , intothedeep : 'DIVE' , energize : 'ENERGIZE' ,
89+ forward : 'FORWARD' , gameChangers : 'GAMECHANGERS' , inshow : 'INSHOW' ,
90+ rise : 'RISE' , discord : 'Discord' , app : 'App' , ScoutSheet : 'ScoutSheet' ,
91+ tranks : 'Teams' , tauto : 'Auto' , ttele : 'TeleOp' , tendgame : 'Endgame' ,
92+ mranks : 'Matches' , qual : 'Qualifiers' , finals : 'Finals' , premier : 'Premier' ,
93+ tac : 'Terms & Conditions' , privacy : 'Privacy Policy' , systemstatus : 'Systems Status' ,
8694 } ;
8795
8896 const currentPage = routeLabels [ pathname ?. split ( '/' ) . pop ( ) || '' ] || '' ;
89-
9097 const sidebarTranslateX = useRef ( new Animated . Value ( sidebarVisible ? 0 : - 209 ) ) . current ;
9198 const overlayOpacity = useRef ( new Animated . Value ( sidebarVisible ? 1 : 0 ) ) . current ;
9299 const sidebarWidth = useRef ( new Animated . Value ( 180 ) ) . current ;
93100
94- // Set browser tab title based on current page and context
95101 useEffect ( ( ) => {
96102 const pathSegments = pathname ?. split ( '/' ) . filter ( Boolean ) || [ ] ;
97103 const lastSegment = pathSegments [ pathSegments . length - 1 ] || 'index' ;
98104 const pageTitle = routeLabels [ lastSegment ] || 'ARES' ;
99-
100- // Check if current page is a dashboard (any page in the dashboards folder)
101105 const isDashboard = pathname ?. includes ( '/dashboards/' ) ;
102- // Check if current page is a rankings page
103- const isRankingsPage = lastSegment === 'tranks' || lastSegment === 'mranks' || lastSegment === 'tauto' || lastSegment === 'ttele' || lastSegment === 'tendgame' ;
106+ const isRankingsPage = [ 'tranks' , 'mranks' , 'tauto' , 'ttele' , 'tendgame' ] . includes ( lastSegment ) ;
104107
105108 let fullTitle = pageTitle ;
106-
107- // If it's a dashboard, use "Team [number]" from customSuffix
108109 if ( isDashboard ) {
109110 fullTitle = customSuffix ? `${ customSuffix } ` : 'Team' ;
110111 } else if ( isRankingsPage && customSuffix ) {
111- // Add customSuffix (year) to rankings pages
112112 fullTitle += ` - ${ customSuffix } ` ;
113113 }
114114
115115 if ( typeof document !== 'undefined' ) {
116116 document . title = `${ fullTitle } | ARES` ;
117117 }
118- } , [ pathname , customSuffix , routeLabels ] ) ;
118+ } , [ pathname , customSuffix ] ) ;
119119
120120 const isDesktop = screenWidth > 800 ;
121121
122- // Create theme object to avoid repetitive conditional styling
123- const theme = {
124- backgroundColor : isDarkMode ? 'rgba(42, 42, 42, 1)' : '#F8FAFC' ,
125- contentBackground : isDarkMode ? 'rgba(42, 42, 42, 0.8)' : '#F8FAFC' ,
126- pageBackground : isDarkMode ? 'rgba(42, 42, 42, 1)' : '#fff' ,
127- sidebarBackground : isDarkMode ? 'rgba(42, 42, 42, 1)' : '#fff' ,
128- closeButtonBackground : isDarkMode ? 'rgba(42, 42, 42, 0.8)' : '#fff' ,
129- closeButtonTouchBackground : isDarkMode ? 'rgba(42, 42, 42, 1)' : '#fff' ,
130- iconFill : isDarkMode ? '#fff' : '#000' ,
131- } ;
132-
133122 const onRefresh = async ( ) => {
134123 setRefreshing ( true ) ;
135124 router . replace ( usePathname ( ) as any ) ;
@@ -140,7 +129,6 @@ function InnerLayout() {
140129 const subscription = Dimensions . addEventListener ( 'change' , ( { window } ) => {
141130 setScreenWidth ( window . width ) ;
142131 } ) ;
143-
144132 return ( ) => subscription ?. remove ( ) ;
145133 } , [ ] ) ;
146134
@@ -152,7 +140,7 @@ function InnerLayout() {
152140 useNativeDriver : false ,
153141 } ) . start ( ) ;
154142 }
155- } , [ sidebarVisible , isDesktop , sidebarWidth ] ) ;
143+ } , [ sidebarVisible , isDesktop ] ) ;
156144
157145 useEffect ( ( ) => {
158146 if ( ! isDesktop ) {
@@ -169,22 +157,19 @@ function InnerLayout() {
169157 } ) ,
170158 ] ) . start ( ) ;
171159 }
172- } , [ sidebarVisible , isDesktop , sidebarTranslateX , overlayOpacity ] ) ;
160+ } , [ sidebarVisible , isDesktop ] ) ;
173161
174- // Don't render until fonts are loaded and dark mode is initialized
175162 if ( ! fontsLoaded || isLoading ) {
176- // Use a neutral background during loading to prevent flash
177- return (
178- < View style = { [ styles . loadingContainer , { backgroundColor : '#F8FAFC' } ] } >
179- { /* You can add a loading spinner here if needed */ }
180- </ View >
181- ) ;
163+ return < View style = { [ styles . loadingContainer , { backgroundColor : theme . backgroundColor } ] } /> ;
182164 }
183165
166+ // barStyle logic fixed: 'light-content' shows white text on dark background
167+ const barStyle = isDarkMode ? 'light-content' : 'dark-content' ;
168+
184169 if ( pathname . includes ( '/auth' ) ) {
185170 return (
186- < View style = { [ { flex : 1 } , { backgroundColor : theme . backgroundColor } ] } >
187- < StatusBar barStyle = { isDarkMode ? 'dark-content' : 'light-content' } backgroundColor = { theme . backgroundColor } />
171+ < View style = { { flex : 1 , backgroundColor : theme . backgroundColor } } >
172+ < StatusBar barStyle = { barStyle } backgroundColor = { theme . backgroundColor } />
188173 < Slot />
189174 </ View >
190175 ) ;
@@ -193,17 +178,15 @@ function InnerLayout() {
193178 if ( isDesktop ) {
194179 return (
195180 < View style = { [ styles2 . container , { backgroundColor : theme . backgroundColor } ] } >
196- < StatusBar barStyle = { isDarkMode ? 'dark-content' : 'light-content' } backgroundColor = { theme . backgroundColor } />
181+ < StatusBar barStyle = { barStyle } backgroundColor = { theme . backgroundColor } />
197182 < Animated . View style = { [ styles2 . sidebar , { width : sidebarWidth , backgroundColor : theme . sidebarBackground } ] } >
198183 { sidebarVisible && < LeftSidebar close = { ( ) => setSidebarVisible ( false ) } /> }
199184 </ Animated . View >
200185
201186 < View style = { [ styles2 . contentArea , { backgroundColor : theme . contentBackground } ] } >
202187 < HeaderBar toggleSidebar = { ( ) => setSidebarVisible ( ! sidebarVisible ) } currentPage = { currentPage } />
203188 < ScrollView
204- refreshControl = {
205- < RefreshControl refreshing = { refreshing } onRefresh = { onRefresh } />
206- }
189+ refreshControl = { < RefreshControl refreshing = { refreshing } onRefresh = { onRefresh } /> }
207190 contentContainerStyle = { [ styles2 . scrollContent , { backgroundColor : theme . backgroundColor } ] }
208191 >
209192 < View style = { [ styles . pageContent , { backgroundColor : theme . pageBackground } ] } >
@@ -218,13 +201,11 @@ function InnerLayout() {
218201
219202 return (
220203 < View style = { [ styles . container , { backgroundColor : theme . backgroundColor } ] } >
221- < StatusBar barStyle = { isDarkMode ? 'dark-content' : 'light-content' } backgroundColor = { theme . backgroundColor } />
204+ < StatusBar barStyle = { barStyle } backgroundColor = { theme . backgroundColor } />
222205 < View style = { [ styles . contentArea , { backgroundColor : theme . backgroundColor } ] } >
223206 < HeaderBar toggleSidebar = { ( ) => setSidebarVisible ( ! sidebarVisible ) } currentPage = { currentPage } />
224207 < ScrollView
225- refreshControl = {
226- < RefreshControl refreshing = { refreshing } onRefresh = { onRefresh } />
227- }
208+ refreshControl = { < RefreshControl refreshing = { refreshing } onRefresh = { onRefresh } /> }
228209 contentContainerStyle = { [ styles . scrollContent , { backgroundColor : theme . backgroundColor } ] }
229210 >
230211 < View style = { [ styles . pageContent , { backgroundColor : theme . pageBackground } ] } >
@@ -236,34 +217,15 @@ function InnerLayout() {
236217
237218 { sidebarVisible && (
238219 < Animated . View style = { [ styles . blurOverlay , { opacity : overlayOpacity } ] } >
239- < TouchableOpacity
240- style = { { flex : 1 } }
241- onPress = { ( ) => setSidebarVisible ( false ) }
242- activeOpacity = { 1 }
243- />
220+ < TouchableOpacity style = { { flex : 1 } } onPress = { ( ) => setSidebarVisible ( false ) } activeOpacity = { 1 } />
244221 </ Animated . View >
245222 ) }
246223
247- < Animated . View style = { [
248- styles . sidebar ,
249- {
250- transform : [ { translateX : sidebarTranslateX } ] ,
251- backgroundColor : theme . sidebarBackground
252- }
253- ] } >
224+ < Animated . View style = { [ styles . sidebar , { transform : [ { translateX : sidebarTranslateX } ] , backgroundColor : theme . sidebarBackground } ] } >
254225 < LeftSidebar close = { ( ) => setSidebarVisible ( false ) } />
255226 { sidebarVisible && (
256- < Animated . View style = { [
257- styles . closeButton ,
258- {
259- opacity : overlayOpacity ,
260- backgroundColor : theme . closeButtonBackground
261- }
262- ] } >
263- < TouchableOpacity
264- style = { [ styles . closeButtonTouch , { backgroundColor : theme . closeButtonTouchBackground } ] }
265- onPress = { ( ) => setSidebarVisible ( false ) }
266- >
227+ < Animated . View style = { [ styles . closeButton , { opacity : overlayOpacity , backgroundColor : theme . closeButtonBackground } ] } >
228+ < TouchableOpacity style = { [ styles . closeButtonTouch , { backgroundColor : theme . closeButtonTouchBackground } ] } onPress = { ( ) => setSidebarVisible ( false ) } >
267229 < Cancel width = { 16 } height = { 16 } fill = { theme . iconFill } />
268230 </ TouchableOpacity >
269231 </ Animated . View >
@@ -274,78 +236,21 @@ function InnerLayout() {
274236}
275237
276238const styles = StyleSheet . create ( {
277- loadingContainer : {
278- flex : 1 ,
279- justifyContent : 'center' ,
280- alignItems : 'center' ,
281- } ,
282- container : {
283- flex : 1 ,
284- } ,
285- contentArea : {
286- flex : 1 ,
287- flexDirection : 'column' ,
288- } ,
289- pageContent : {
290- flex : 1 ,
291- padding : 20 ,
292- } ,
293- scrollContent : {
294- flexGrow : 1 ,
295- justifyContent : 'space-between' ,
296- } ,
297- sidebar : {
298- position : 'absolute' ,
299- top : 0 ,
300- left : 0 ,
301- width : 209 ,
302- height : '100%' ,
303- zIndex : 1000 ,
304- } ,
305- blurOverlay : {
306- position : 'absolute' ,
307- top : 0 ,
308- left : 0 ,
309- right : 0 ,
310- bottom : 0 ,
311- backgroundColor : 'rgba(0, 0, 0, 0.3)' ,
312- zIndex : 999 ,
313- } ,
314- closeButton : {
315- position : 'absolute' ,
316- top : 10 ,
317- right : - 40 ,
318- zIndex : 1001 ,
319- borderRadius : 6 ,
320- } ,
321- closeButtonTouch : {
322- width : 30 ,
323- height : 30 ,
324- borderRadius : 6 ,
325- justifyContent : 'center' ,
326- alignItems : 'center' ,
327- elevation : 5 ,
328- } ,
239+ loadingContainer : { flex : 1 , justifyContent : 'center' , alignItems : 'center' } ,
240+ container : { flex : 1 , flexDirection : 'row' } ,
241+ contentArea : { flex : 1 , flexDirection : 'column' } ,
242+ pageContent : { flex : 1 , padding : 20 } ,
243+ scrollContent : { flexGrow : 1 , justifyContent : 'space-between' } ,
244+ sidebar : { position : 'absolute' , top : 0 , left : 0 , width : 209 , height : '100%' , zIndex : 1000 } ,
245+ blurOverlay : { position : 'absolute' , top : 0 , left : 0 , right : 0 , bottom : 0 , backgroundColor : 'rgba(0, 0, 0, 0.3)' , zIndex : 999 } ,
246+ closeButton : { position : 'absolute' , top : 10 , right : - 40 , zIndex : 1001 , borderRadius : 6 } ,
247+ closeButtonTouch : { width : 30 , height : 30 , borderRadius : 6 , justifyContent : 'center' , alignItems : 'center' } ,
329248} ) ;
330249
331250const styles2 = StyleSheet . create ( {
332- container : {
333- flexDirection : 'row' ,
334- flex : 1 ,
335- } ,
336- sidebar : {
337- overflow : 'hidden' ,
338- } ,
339- contentArea : {
340- flex : 1 ,
341- flexDirection : 'column' ,
342- } ,
343- pageContent : {
344- flex : 1 ,
345- padding : 20 ,
346- } ,
347- scrollContent : {
348- flexGrow : 1 ,
349- justifyContent : 'space-between' ,
350- } ,
251+ container : { flexDirection : 'row' , flex : 1 } ,
252+ sidebar : { overflow : 'hidden' } ,
253+ contentArea : { flex : 1 , flexDirection : 'column' } ,
254+ pageContent : { flex : 1 , padding : 20 } ,
255+ scrollContent : { flexGrow : 1 , justifyContent : 'space-between' } ,
351256} ) ;
0 commit comments