Skip to content

Commit 89c7924

Browse files
committed
major improvements
1 parent 4eaccf4 commit 89c7924

File tree

6 files changed

+650
-342
lines changed

6 files changed

+650
-342
lines changed

mobile/app/game/[id].tsx

Lines changed: 58 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)