@@ -86,7 +86,7 @@ export default function GameScreen() {
8686 const [ guessPosition , setGuessPosition ] = useState < { lat : number ; lng : number } | null > ( null ) ;
8787 // Map is HIDDEN by default on mobile, matching web behavior
8888 const [ miniMapShown , setMiniMapShown ] = useState ( false ) ;
89- // Only mount the map once it's first shown (avoids initializing at height 0)
89+ // Mount the map eagerly once loading completes to avoid first-touch issues
9090 const [ mapMounted , setMapMounted ] = useState ( false ) ;
9191
9292 // Animation values
@@ -95,12 +95,15 @@ export default function GameScreen() {
9595 const bannerSlideAnim = useRef ( new Animated . Value ( 300 ) ) . current ;
9696 const fabScaleAnim = useRef ( new Animated . Value ( 1 ) ) . current ;
9797
98- // Mount map on first show so it initializes with actual size
98+ // Mount map eagerly once game loads — prevents first-touch being swallowed
99+ // by a freshly-mounted MapView when showing the first round's result
99100 useEffect ( ( ) => {
100- if ( miniMapShown || gameState . isShowingResult ) {
101- setMapMounted ( true ) ;
101+ if ( ! isLoading && ! mapMounted ) {
102+ // Small delay so the initial render settles before adding the MapView
103+ const timer = setTimeout ( ( ) => setMapMounted ( true ) , 300 ) ;
104+ return ( ) => clearTimeout ( timer ) ;
102105 }
103- } , [ miniMapShown , gameState . isShowingResult ] ) ;
106+ } , [ isLoading , mapMounted ] ) ;
104107
105108 // Animate map slide in/out
106109 useEffect ( ( ) => {
@@ -149,20 +152,22 @@ export default function GameScreen() {
149152 } , [ miniMapShown , gameState . isShowingResult ] ) ;
150153
151154 // Banner slide animation
155+ // useNativeDriver: false ensures JS-side touch targets match the banner's
156+ // visual position, preventing the "first tap ignored" bug on first round
152157 useEffect ( ( ) => {
153158 if ( gameState . isShowingResult ) {
154159 bannerSlideAnim . setValue ( 300 ) ;
155160 Animated . spring ( bannerSlideAnim , {
156161 toValue : 0 ,
157162 friction : 8 ,
158163 tension : 50 ,
159- useNativeDriver : true ,
164+ useNativeDriver : false ,
160165 } ) . start ( ) ;
161166 } else {
162167 Animated . timing ( bannerSlideAnim , {
163168 toValue : 300 ,
164169 duration : 200 ,
165- useNativeDriver : true ,
170+ useNativeDriver : false ,
166171 } ) . start ( ) ;
167172 }
168173 } , [ gameState . isShowingResult ] ) ;
@@ -426,18 +431,22 @@ export default function GameScreen() {
426431 ] }
427432 pointerEvents = { miniMapShown || gameState . isShowingResult ? 'auto' : 'none' }
428433 >
429- { mapMounted && (
430- < GuessMap
431- guessPosition = { guessPosition }
432- actualPosition = {
433- gameState . isShowingResult
434- ? { lat : currentLocation . lat , lng : currentLocation . long }
435- : undefined
436- }
437- onMapPress = { handleMapPress }
438- isExpanded = { true }
439- />
440- ) }
434+ { /* Inner wrapper gives MapView a fixed height so initialRegion works
435+ even when the animated outer container starts at 0px height */ }
436+ < View style = { { position : 'absolute' , top : 0 , left : 0 , right : 0 , height : height } } >
437+ { mapMounted && (
438+ < GuessMap
439+ guessPosition = { guessPosition }
440+ actualPosition = {
441+ gameState . isShowingResult
442+ ? { lat : currentLocation . lat , lng : currentLocation . long }
443+ : undefined
444+ }
445+ onMapPress = { handleMapPress }
446+ isExpanded = { true }
447+ />
448+ ) }
449+ </ View >
441450 </ Animated . View >
442451
443452 { /* ═══ MOBILE GUESS BUTTONS - above map when map is open ═══ */ }
@@ -545,6 +554,11 @@ export default function GameScreen() {
545554 ] }
546555 >
547556 < View style = { styles . endBannerContent } >
557+ { /* Round & score context */ }
558+ < Text style = { styles . endBannerRound } >
559+ Round { gameState . currentRound } /{ gameState . totalRounds }
560+ </ Text >
561+
548562 { /* Distance text */ }
549563 < Text style = { styles . endBannerDistance } >
550564 { lastGuess . distance >= 1
@@ -558,6 +572,11 @@ export default function GameScreen() {
558572 { lastGuess . points . toLocaleString ( ) } points
559573 </ Text >
560574
575+ { /* Running total */ }
576+ < Text style = { styles . endBannerTotal } >
577+ Total: { gameState . totalScore . toLocaleString ( ) } / { gameState . totalRounds * 5000 }
578+ </ Text >
579+
561580 { /* Next Round / View Results button */ }
562581 < Pressable
563582 onPress = { handleNextRound }
@@ -631,7 +650,7 @@ const styles = StyleSheet.create({
631650 paddingTop : spacing . sm ,
632651 } ,
633652 timerPill : {
634- backgroundColor : colors . primaryTransparent ,
653+ backgroundColor : Platform . OS === 'android' ? '#1a4423' : colors . primaryTransparent ,
635654 borderRadius : borderRadius . xl ,
636655 paddingHorizontal : spacing . lg ,
637656 paddingVertical : spacing . sm ,
@@ -787,24 +806,31 @@ const styles = StyleSheet.create({
787806 zIndex : 1001 ,
788807 } ,
789808 endBannerContent : {
790- backgroundColor : 'rgba(0, 0, 0, 0.3)' ,
791- backdropFilter : 'blur(10px)' ,
792- borderRadius : 10 ,
809+ backgroundColor : 'rgba(17, 43, 24, 0.92)' ,
810+ borderRadius : 12 ,
793811 marginHorizontal : spacing . lg ,
794812 marginBottom : spacing . md ,
795813 padding : spacing . xl ,
796814 alignItems : 'center' ,
797815 gap : spacing . sm ,
816+ borderWidth : 1 ,
817+ borderColor : 'rgba(255, 255, 255, 0.1)' ,
798818 ...Platform . select ( {
799819 ios : {
800820 shadowColor : '#000' ,
801821 shadowOffset : { width : 0 , height : 4 } ,
802- shadowOpacity : 0.3 ,
803- shadowRadius : 12 ,
822+ shadowOpacity : 0.4 ,
823+ shadowRadius : 16 ,
804824 } ,
805- android : { elevation : 8 } ,
825+ android : { elevation : 12 } ,
806826 } ) ,
807827 } ,
828+ endBannerRound : {
829+ color : 'rgba(255, 255, 255, 0.6)' ,
830+ fontSize : fontSizes . sm ,
831+ fontWeight : '600' ,
832+ textAlign : 'center' ,
833+ } ,
808834 endBannerDistance : {
809835 color : colors . white ,
810836 fontSize : fontSizes . lg ,
@@ -816,6 +842,12 @@ const styles = StyleSheet.create({
816842 fontWeight : 'bold' ,
817843 textAlign : 'center' ,
818844 } ,
845+ endBannerTotal : {
846+ color : 'rgba(255, 255, 255, 0.7)' ,
847+ fontSize : fontSizes . sm ,
848+ fontWeight : '500' ,
849+ textAlign : 'center' ,
850+ } ,
819851 nextRoundBtn : {
820852 marginTop : spacing . sm ,
821853 paddingVertical : spacing . md ,
0 commit comments