diff --git a/redux/GamesSlice.ts b/redux/GamesSlice.ts index edb77553..59ec0371 100644 --- a/redux/GamesSlice.ts +++ b/redux/GamesSlice.ts @@ -14,6 +14,7 @@ export interface GameState { roundCurrent: number; roundTotal: number; playerIds: string[]; + locked?: boolean; } const gamesAdapter = createEntityAdapter({ diff --git a/src/components/GameBottomSheet.tsx b/src/components/GameBottomSheet.tsx index 62de88b0..77d4c0ea 100644 --- a/src/components/GameBottomSheet.tsx +++ b/src/components/GameBottomSheet.tsx @@ -5,12 +5,12 @@ import { NativeStackNavigationProp } from '@react-navigation/native-stack'; import { ParamListBase } from '@react-navigation/native'; import BottomSheet, { BottomSheetScrollView } from '@gorhom/bottom-sheet'; -import { useAppSelector } from '../../redux/hooks'; +import { useAppDispatch, useAppSelector } from '../../redux/hooks'; import Rounds from '../components/Rounds'; -import { selectGameById } from '../../redux/GamesSlice'; +import { selectGameById, updateGame } from '../../redux/GamesSlice'; import { systemBlue } from '../constants'; import Animated, { Extrapolate, interpolate, useAnimatedStyle, useSharedValue } from 'react-native-reanimated'; -import { TouchableOpacity } from 'react-native-gesture-handler'; +import { TouchableOpacity, TouchableWithoutFeedback } from 'react-native'; import { Icon } from 'react-native-elements'; /** @@ -38,6 +38,20 @@ const GameBottomSheet: React.FunctionComponent = ({ navigation, container // variables const snapPoints = useMemo(() => [bottomSheetHeight, '60%', '100%'], []); + const dispatch = useAppDispatch(); + + /** + * Lock the game + */ + const setLock = () => dispatch( + updateGame({ + id: currentGame.id, + changes: { + locked: !currentGame.locked, + } + }) + ); + // State variable for the current snap point index const [, setSnapPointIndex] = useState(0); @@ -100,12 +114,23 @@ const GameBottomSheet: React.FunctionComponent = ({ navigation, container - sheetTitlePress()}> - {currentGame.title} - - navigation.navigate('Settings')}> - Edit - + sheetTitlePress()}> + + {currentGame.title} + + + {currentGame.locked && + { bottomSheetRef.current?.snapToIndex(snapPoints.length - 1); }} + > + Locked + + } + {!currentGame.locked && + navigation.navigate('Settings')}> + Edit + + } @@ -115,12 +140,27 @@ const GameBottomSheet: React.FunctionComponent = ({ navigation, container - navigation.navigate('Share')}> + navigation.navigate('Share')}> Share + + + + + + {currentGame.locked ? "Unlock" : "Lock"} + + + @@ -135,15 +175,15 @@ const styles = StyleSheet.create({ justifyContent: 'space-between', paddingHorizontal: 10, }, - sheetHeader: { - color: 'white', + sheetTitle: { flex: 1, + color: 'white', fontSize: 20, fontWeight: 'bold', paddingHorizontal: 10, paddingTop: 0, }, - sheetHeaderButton: { + editButton: { color: systemBlue, fontSize: 20, paddingHorizontal: 10, @@ -153,6 +193,7 @@ const styles = StyleSheet.create({ paddingHorizontal: 20, }, shareButton: { + width: 100, margin: 5, padding: 10, paddingHorizontal: 20, diff --git a/src/components/GameListItem.tsx b/src/components/GameListItem.tsx index 191ab128..b24451c2 100644 --- a/src/components/GameListItem.tsx +++ b/src/components/GameListItem.tsx @@ -175,7 +175,10 @@ const GameListItem: React.FunctionComponent = ({ navigation, game, index actions={actions}> - {game.title} + + {game.title} + {game.locked && } + {game.dateCreated} diff --git a/src/components/Headers/GameHeader.tsx b/src/components/Headers/GameHeader.tsx index 1176055e..0836b832 100644 --- a/src/components/Headers/GameHeader.tsx +++ b/src/components/Headers/GameHeader.tsx @@ -17,10 +17,10 @@ import CustomHeader from './CustomHeader'; interface PrevRoundButtonProps { prevRoundHandler: () => void; - roundCurrent: number; + visible: boolean; } -const PrevRoundButton: React.FunctionComponent = ({ prevRoundHandler, roundCurrent }) => { +const PrevRoundButton: React.FunctionComponent = ({ prevRoundHandler, visible }) => { return ( @@ -28,7 +28,7 @@ const PrevRoundButton: React.FunctionComponent = ({ prevRo type="font-awesome-5" size={20} color={systemBlue} - style={{ opacity: roundCurrent == 0 ? 0 : 1 }} + style={{ opacity: visible ? 0 : 1 }} /> ); @@ -36,16 +36,19 @@ const PrevRoundButton: React.FunctionComponent = ({ prevRo interface NextRoundButtonProps { nextRoundHandler: () => void; + visible: boolean; } -const NextRoundButton: React.FunctionComponent = ({ nextRoundHandler }) => { +const NextRoundButton: React.FunctionComponent = ({ nextRoundHandler, visible }) => { return ( + color={systemBlue} + style={{ opacity: visible ? 0 : 1 }} + /> ); }; @@ -64,6 +67,7 @@ const GameHeader: React.FunctionComponent = ({ navigation }) => { ); const currentGame = useAppSelector(state => selectGameById(state, currentGameId)); const roundCurrent = useAppSelector(state => selectGameById(state, currentGameId)?.roundCurrent || 0); + const lastRoundIndex = useAppSelector(state => selectGameById(state, currentGameId)?.roundTotal || 0); if (currentGame == null) { return = ({ navigation }) => { />; } + const isFirstRound = roundCurrent == 0; + const isLastRound = roundCurrent >= lastRoundIndex; + const nextRoundHandler = async () => { + if (isLastRound && currentGame.locked) return; + dispatch(roundNext(currentGame.id)); await analytics().logEvent('round_change', { game_id: currentGameId, @@ -81,6 +90,8 @@ const GameHeader: React.FunctionComponent = ({ navigation }) => { }; const prevRoundHandler = async () => { + if (isFirstRound) return; + dispatch(roundPrevious(currentGame.id)); await analytics().logEvent('round_change', { game_id: currentGameId, @@ -95,9 +106,9 @@ const GameHeader: React.FunctionComponent = ({ navigation }) => { } headerCenter={<> - + Round {roundCurrent + 1} - + } headerRight={} /> diff --git a/src/components/PlayerTiles/AdditionTile/TouchSurface.tsx b/src/components/PlayerTiles/AdditionTile/TouchSurface.tsx index 6629f55a..283075a4 100644 --- a/src/components/PlayerTiles/AdditionTile/TouchSurface.tsx +++ b/src/components/PlayerTiles/AdditionTile/TouchSurface.tsx @@ -46,6 +46,8 @@ export const TouchSurface: React.FunctionComponent = ( }; const scoreChangeHandler = () => { + if (currentGame.locked) return; + if (showPointParticles) { addParticle(); } @@ -63,7 +65,7 @@ export const TouchSurface: React.FunctionComponent = ( return (