Skip to content

Commit

Permalink
Merge pull request #346 from wyne/sheet-coordination
Browse files Browse the repository at this point in the history
Close GameSheet on AddendModal open
  • Loading branch information
wyne authored Nov 17, 2023
2 parents 41363ae + 986199e commit bfcb46e
Show file tree
Hide file tree
Showing 10 changed files with 117 additions and 89 deletions.
21 changes: 12 additions & 9 deletions App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import { Navigation } from './src/Navigation';
import { View } from 'react-native';
import { GestureHandlerRootView } from 'react-native-gesture-handler';
import analytics from '@react-native-firebase/analytics';
import { PointSelectModalContextProvider } from './src/contexts/PointSelectModalContext';
import { AddendModalContextProvider } from './src/components/Sheets/AddendModalContext';
import { GameSheetContextProvider } from './src/components/Sheets/GameSheetContext';

if (process.env.EXPO_PUBLIC_FIREBASE_ANALYTICS == "false") {
analytics().setAnalyticsCollectionEnabled(false);
Expand All @@ -17,14 +18,16 @@ export default function App() {
return (
<View style={{ flex: 1, backgroundColor: '#fff' }}>
<GestureHandlerRootView style={{ flex: 1 }}>
<PointSelectModalContextProvider>
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
<StatusBar />
<Navigation />
</PersistGate>
</Provider>
</PointSelectModalContextProvider>
<GameSheetContextProvider>
<AddendModalContextProvider>
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
<StatusBar />
<Navigation />
</PersistGate>
</Provider>
</AddendModalContextProvider>
</GameSheetContextProvider>
</GestureHandlerRootView>
</View>
);
Expand Down
2 changes: 2 additions & 0 deletions redux/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ const settingsPersistConfig = {
whitelist: [
'home_fullscreen',
'multiplier',
'addendOne',
'addendTwo',
'currentGameId',
'onboarded',
'showPointParticles'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,23 @@ import { Text, View, StyleSheet, TouchableHighlight } from 'react-native';

import { useAppSelector } from '../../../redux/hooks';
import { systemBlue } from '../../constants';
import { usePointSelectModalContext } from '../../contexts/PointSelectModalContext';
import { useAddendModalContext } from '../Sheets/AddendModalContext';
import { useGameSheetContext } from '../Sheets/GameSheetContext';

const MultiplierButton: React.FunctionComponent = ({ }) => {
const AddendButton: React.FunctionComponent = ({ }) => {
const addendOne = useAppSelector(state => state.settings.addendOne);
const addendTwo = useAppSelector(state => state.settings.addendTwo);

const pointSelectorModalRef = usePointSelectModalContext();
const adddendModalRef = useAddendModalContext();
const gameSheetRef = useGameSheetContext();

const handlePress = () => {
if (pointSelectorModalRef == null) {
if (adddendModalRef == null) {
return;
}

pointSelectorModalRef.current?.present();
gameSheetRef?.current?.snapToIndex(0);
adddendModalRef.current?.present();
};

return (
Expand All @@ -43,4 +46,4 @@ const styles = StyleSheet.create({
},
});

export default MultiplierButton;
export default AddendButton;
4 changes: 2 additions & 2 deletions src/components/Headers/GameHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { selectGameById } from '../../../redux/GamesSlice';
import { systemBlue } from '../../constants';
import { Button } from 'react-native-elements';
import MenuButton from '../Buttons/MenuButton';
import MultiplierButton from '../Buttons/MultiplierButton';
import AddendButton from '../Buttons/AddendButton';
import CustomHeader from './CustomHeader';

interface PrevRoundButtonProps {
Expand Down Expand Up @@ -110,7 +110,7 @@ const GameHeader: React.FunctionComponent<Props> = ({ navigation }) => {
<Text style={styles.title}>Round {roundCurrent + 1}</Text>
<NextRoundButton nextRoundHandler={nextRoundHandler} visible={isLastRound && (currentGame.locked || false)} />
</>}
headerRight={!currentGame.locked && <MultiplierButton />}
headerRight={!currentGame.locked && <AddendButton />}
/>
);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
import React, { useCallback, useMemo } from 'react';
import { View, StyleSheet, Text } from 'react-native';
import { useAppDispatch, useAppSelector } from '../../redux/hooks';
import { useAppDispatch, useAppSelector } from '../../../redux/hooks';
import { BottomSheetBackdrop, BottomSheetBackdropProps, BottomSheetModal } from '@gorhom/bottom-sheet';

import { usePointSelectModalContext } from '../contexts/PointSelectModalContext';
import { useAddendModalContext } from './AddendModalContext';
import { Picker } from '@react-native-picker/picker';
import { setAddendOne, setAddendTwo, setMultiplier } from '../../redux/SettingsSlice';
import { setAddendOne, setAddendTwo, setMultiplier } from '../../../redux/SettingsSlice';

interface Props {
}

const PointSelectorBottomSheet: React.FunctionComponent<Props> = ({ }) => {
const AddendModal: React.FunctionComponent<Props> = ({ }) => {
const addendOne = useAppSelector(state => state.settings.addendOne);
const addendTwo = useAppSelector(state => state.settings.addendTwo);

const addendOptions = [1, 5, 10, 20, 50];
// Array of 1 to 50
const addendOptions = Array.from({ length: 50 }, (_, i) => i + 1);

const dispatch = useAppDispatch();

Expand All @@ -30,14 +31,14 @@ const PointSelectorBottomSheet: React.FunctionComponent<Props> = ({ }) => {
}, []);

// ref
const pointSelectorModalRef = usePointSelectModalContext();
const addendModalRef = useAddendModalContext();

// variables
const snapPoints = useMemo(() => [1, 320], []);

const handleSheetChanges = useCallback((index: number) => {
if (index === 0 && pointSelectorModalRef != null) {
pointSelectorModalRef.current?.close();
if (index === 0) {
addendModalRef?.current?.close();
}
}, []);

Expand All @@ -54,7 +55,7 @@ const PointSelectorBottomSheet: React.FunctionComponent<Props> = ({ }) => {

return (
<BottomSheetModal
ref={pointSelectorModalRef}
ref={addendModalRef}
index={1}
enablePanDownToClose={true}
snapPoints={snapPoints}
Expand Down Expand Up @@ -133,4 +134,4 @@ const styles = StyleSheet.create({
},
});

export default PointSelectorBottomSheet;
export default AddendModal;
18 changes: 18 additions & 0 deletions src/components/Sheets/AddendModalContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import React, { createContext, useContext, useRef } from 'react';
import { BottomSheetModal } from '@gorhom/bottom-sheet';

const AddendModalContext = createContext<React.RefObject<BottomSheetModal> | null>(null);

export const AddendModalContextProvider: React.FC<React.PropsWithChildren> = (props) => {
const addendModalRef = useRef<BottomSheetModal>(null);

return (
<AddendModalContext.Provider value={addendModalRef} >
{props.children}
</AddendModalContext.Provider>
);
};

export const useAddendModalContext = () => {
return useContext(AddendModalContext);
};
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import React, { useCallback, useMemo, useRef, useState } from 'react';
import React, { useCallback, useMemo, useState } from 'react';
import { View, StyleSheet, Text } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { NativeStackNavigationProp } from '@react-navigation/native-stack';
import { ParamListBase } from '@react-navigation/native';
import BottomSheet, { BottomSheetBackdrop, BottomSheetBackdropProps, BottomSheetScrollView } from '@gorhom/bottom-sheet';

import { useAppDispatch, useAppSelector } from '../../redux/hooks';
import Rounds from '../components/Rounds';
import { selectGameById, updateGame } from '../../redux/GamesSlice';
import { systemBlue } from '../constants';
import { useAppDispatch, useAppSelector } from '../../../redux/hooks';
import Rounds from '../Rounds';
import { selectGameById, updateGame } from '../../../redux/GamesSlice';
import { systemBlue } from '../../constants';
import Animated, { Extrapolate, interpolate, useAnimatedStyle, useSharedValue } from 'react-native-reanimated';
import { TouchableOpacity, TouchableWithoutFeedback } from 'react-native';
import { Icon } from 'react-native-elements';
import { useGameSheetContext } from './GameSheetContext';

/**
* Height of the bottom sheet
Expand All @@ -23,7 +24,7 @@ interface Props {
containerHeight: number;
}

const GameBottomSheet: React.FunctionComponent<Props> = ({ navigation, containerHeight }) => {
const GameSheet: React.FunctionComponent<Props> = ({ navigation, containerHeight }) => {
const currentGameId = useAppSelector(state => state.settings.currentGameId);
if (typeof currentGameId == 'undefined') return null;

Expand All @@ -33,7 +34,7 @@ const GameBottomSheet: React.FunctionComponent<Props> = ({ navigation, container
if (currentGame == undefined) return null;

// ref
const bottomSheetRef = useRef<BottomSheet>(null);
const gameSheetRef = useGameSheetContext();

// variables
const snapPoints = useMemo(() => [bottomSheetHeight, '60%', '100%'], []);
Expand Down Expand Up @@ -68,7 +69,7 @@ const GameBottomSheet: React.FunctionComponent<Props> = ({ navigation, container
const sheetTitlePress = () => {
setSnapPointIndex((prevIndex) => {
const nextIndex = (prevIndex + 1) % snapPoints.length;
bottomSheetRef.current?.snapToIndex(nextIndex);
gameSheetRef?.current?.snapToIndex(nextIndex);
return nextIndex;
});
};
Expand Down Expand Up @@ -115,7 +116,7 @@ const GameBottomSheet: React.FunctionComponent<Props> = ({ navigation, container

return (
<BottomSheet
ref={bottomSheetRef}
ref={gameSheetRef}
index={0}
onChange={onSheetChange}
snapPoints={snapPoints}
Expand All @@ -137,7 +138,7 @@ const GameBottomSheet: React.FunctionComponent<Props> = ({ navigation, container
</TouchableWithoutFeedback>
{currentGame.locked &&
<Text style={{ color: 'gray', fontSize: 20, paddingHorizontal: 10 }}
onPress={() => { bottomSheetRef.current?.snapToIndex(snapPoints.length - 1); }}
onPress={() => { gameSheetRef?.current?.snapToIndex(snapPoints.length - 1); }}
>
Locked
</Text>
Expand Down Expand Up @@ -221,4 +222,4 @@ const styles = StyleSheet.create({
},
});

export default GameBottomSheet;
export default GameSheet;
21 changes: 21 additions & 0 deletions src/components/Sheets/GameSheetContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React, { createContext, useContext, useRef } from 'react';
import { BottomSheetModalProvider } from '@gorhom/bottom-sheet';
import BottomSheet from '@gorhom/bottom-sheet/lib/typescript/components/bottomSheet/BottomSheet';

const GameSheetContext = createContext<React.RefObject<BottomSheet> | null>(null);

export const GameSheetContextProvider: React.FC<React.PropsWithChildren> = (props) => {
const gameSheetRef = useRef<BottomSheet>(null);

return (
<GameSheetContext.Provider value={gameSheetRef} >
<BottomSheetModalProvider>
{props.children}
</BottomSheetModalProvider>
</GameSheetContext.Provider>
);
};

export const useGameSheetContext = () => {
return useContext(GameSheetContext);
};
18 changes: 0 additions & 18 deletions src/contexts/PointSelectModalContext.tsx

This file was deleted.

63 changes: 30 additions & 33 deletions src/screens/GameScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@ import { ParamListBase } from '@react-navigation/native';
import { useAppSelector } from '../../redux/hooks';
import PlayerTile from '../components/PlayerTile';
import { selectGameById } from '../../redux/GamesSlice';
import GameBottomSheet, { bottomSheetHeight } from '../components/GameBottomSheet';
import PointSelectorBottomSheet from '../components/PointSelectorModal';
import { BottomSheetModalProvider } from '@gorhom/bottom-sheet';
import GameSheet, { bottomSheetHeight } from '../components/Sheets/GameSheet';
import AddendModal from '../components/Sheets/AddendModal';

interface Props {
navigation: NativeStackNavigationProp<ParamListBase, string, undefined>;
Expand Down Expand Up @@ -101,37 +100,35 @@ const ScoreBoardScreen: React.FunctionComponent<Props> = ({ navigation }) => {
}, []);

return (
<BottomSheetModalProvider>
<View style={{ flex: 1 }}>
<View style={[StyleSheet.absoluteFillObject]} onLayout={onLayout}>
<SafeAreaView edges={['left', 'right']} style={
[styles.contentStyle,
{
paddingBottom: fullscreen ? 20 : bottomSheetHeight + 2, // Add 2 to account for the border
}]
} onLayout={layoutHandler} >
{playerIds.map((id, index) => (
width != null && height != null && rows != 0 && cols != 0 &&
<PlayerTile
key={id}
playerId={id}
color={'#' + palette[index % palette.length]}
fontColor={getContrastRatio('#' + palette[index % palette.length], '#000').number > 7 ? "#000000" : "#FFFFFF"}
cols={cols}
rows={rows}
width={calculateTileDimensions(rows, cols).width}
height={calculateTileDimensions(rows, cols).height}
index={index}
/>
))}
</SafeAreaView>
{!fullscreen &&
<GameBottomSheet navigation={navigation} containerHeight={windowHeight} />
}
<PointSelectorBottomSheet />
</View>
<View style={{ flex: 1 }}>
<View style={[StyleSheet.absoluteFillObject]} onLayout={onLayout}>
<SafeAreaView edges={['left', 'right']} style={
[styles.contentStyle,
{
paddingBottom: fullscreen ? 20 : bottomSheetHeight + 2, // Add 2 to account for the border
}]
} onLayout={layoutHandler} >
{playerIds.map((id, index) => (
width != null && height != null && rows != 0 && cols != 0 &&
<PlayerTile
key={id}
playerId={id}
color={'#' + palette[index % palette.length]}
fontColor={getContrastRatio('#' + palette[index % palette.length], '#000').number > 7 ? "#000000" : "#FFFFFF"}
cols={cols}
rows={rows}
width={calculateTileDimensions(rows, cols).width}
height={calculateTileDimensions(rows, cols).height}
index={index}
/>
))}
</SafeAreaView>
{!fullscreen &&
<GameSheet navigation={navigation} containerHeight={windowHeight} />
}
<AddendModal />
</View>
</BottomSheetModalProvider>
</View>
);
};

Expand Down

0 comments on commit bfcb46e

Please sign in to comment.