diff --git a/App.js b/App.js index 6ac5cf6..22bab44 100644 --- a/App.js +++ b/App.js @@ -40,15 +40,15 @@ const GameStack = () => ( contentStyle: { backgroundColor: '#ffffff' }, }} > + + + - - - ); diff --git a/src/components/screens/MapScreen.js b/src/components/screens/MapScreen.js index dcd96aa..0c35885 100644 --- a/src/components/screens/MapScreen.js +++ b/src/components/screens/MapScreen.js @@ -1,49 +1,70 @@ import React, {useCallback, useEffect, useState} from 'react'; -import {ActivityIndicator, StyleSheet, Text, View} from 'react-native'; +import {ActivityIndicator, ScrollView, StyleSheet, Text, TextInput, View} from 'react-native'; import * as Location from 'expo-location'; import {Magnetometer} from 'expo-sensors'; import Screen from '../layout/Screen'; +import {Button, ButtonTray} from '../UI/Button'; import PlayerMapView from '../gameplay/PlayerMapView'; import useGameHook from '../../hooks/useGameHook'; import usePlayerGame from '../../hooks/usePlayerGame'; -import {getSession} from '../../hooks/SessionStore'; +import {getSession, setSessionGroup, setSessionUser} from '../../hooks/SessionStore'; const toHeading = ({x, y}) => { const angle = Math.atan2(y, x) * (180 / Math.PI); return angle < 0 ? angle + 360 : angle; }; -const MapScreen = () => { +const MapScreen = ({navigation}) => { // Initialisation ------------ const session = getSession(); - const {getCaches, claimCache} = useGameHook(); + const {getCaches, claimCache, joinPrivateGame, createPrivateGame, getLobby, getUser} = useGameHook(); // State ---------------------- + const [inGame, setInGame] = useState(Boolean(session.currentGid)); + const [isAdmin, setIsAdmin] = useState(session.isAcceptedAdmin); const [userLocation, setUserLocation] = useState(null); const [heading, setHeading] = useState(null); const [loading, setLoading] = useState(true); const [cacheRecords, setCacheRecords] = useState([]); const [error, setError] = useState(''); + const [gameCode, setGameCode] = useState(''); + const [groupInfo, setGroupInfo] = useState(null); - const subgroupFilter = session.currentSGid; - const {visibleCache, isClaiming, setIsClaiming} = usePlayerGame(userLocation, heading, cacheRecords); + const isPlayer = inGame && !isAdmin; + const {visibleCache, isClaiming, setIsClaiming} = usePlayerGame( + isPlayer ? userLocation : null, + isPlayer ? heading : null, + isPlayer ? cacheRecords : [], + ); // Handlers ------------------- + // Load group info for TeamsEnabled check + useEffect(() => { + if (!session.currentGid) return; + getLobby(session.currentGid).then(setGroupInfo); + }, [inGame]); + + // Load caches for players only const loadCaches = useCallback(async () => { - if (!session.currentGid) { + if (!session.currentGid || isAdmin) { setCacheRecords([]); return; } - const rows = await getCaches(session.currentGid, subgroupFilter); + const rows = await getCaches(session.currentGid, session.currentSGid); setCacheRecords(rows || []); - }, [session.currentGid, subgroupFilter]); + }, [inGame, isAdmin]); useEffect(() => { loadCaches(); }, [loadCaches]); + // Location + compass tracking for players only useEffect(() => { + if (!isPlayer) { + setLoading(false); + return; + } let locationSub; let headingSub; @@ -59,23 +80,46 @@ const MapScreen = () => { locationSub = await Location.watchPositionAsync( {accuracy: Location.Accuracy.Balanced, distanceInterval: 1, timeInterval: 1000}, - (next) => { - setUserLocation({latitude: next.coords.latitude, longitude: next.coords.longitude}); - }, + (next) => setUserLocation({latitude: next.coords.latitude, longitude: next.coords.longitude}), ); Magnetometer.setUpdateInterval(500); - headingSub = Magnetometer.addListener((data) => { setHeading(toHeading(data)); }); + headingSub = Magnetometer.addListener((data) => setHeading(toHeading(data))); setLoading(false); }; start(); - return () => { if (locationSub) locationSub.remove(); if (headingSub) headingSub.remove(); }; - }, []); + }, [isPlayer]); + + const handleJoinGame = async () => { + if (!gameCode.trim()) return; + const result = await joinPrivateGame({JoinCode: gameCode.trim(), Uid: session.currentUid}); + if (!result) return; + setSessionGroup(result.Gid, result.SGid); + setInGame(true); + setIsAdmin(false); + navigation.navigate('TeamScreen'); + }; + + const handleCreateGame = async () => { + const result = await createPrivateGame({ + GroupName: 'My Game', + CreatedByUid: session.currentUid, + TeamsEnabled: false, + MaxMemberSubgroups: 1, + }); + if (!result) return; + const freshUser = await getUser(session.currentUid); + if (freshUser) { + setSessionUser(freshUser); + setInGame(true); + setIsAdmin(true); + } + }; const handleClaim = async (cacheId) => { if (!session.currentGid) return; @@ -91,15 +135,39 @@ const MapScreen = () => { // View ----------------------- - if (!session.currentGid) { + // Not in a game + if (!inGame) { return ( - Join or create a game to use map features. + + +