Skip to content

Commit

Permalink
Merge pull request #362 from wyne/android-picker
Browse files Browse the repository at this point in the history
Android Picker
wyne authored Dec 24, 2023
2 parents 927bc79 + d52af94 commit 67c8ca2
Showing 13 changed files with 3,748 additions and 4,445 deletions.
3 changes: 2 additions & 1 deletion Contributing.md
Original file line number Diff line number Diff line change
@@ -4,12 +4,13 @@ Run any build command remotely by removing `--local` flag.

### Development - Simulator

Prerequisite: `SENTRY_AUTH_TOKEN` in `.env`
For android, use JDK 17.

```zsh
npx react-native-clean-project
npx expo prebuild
eas build --profile development-simulator --platform ios --local
eas build --profile development-simulator --platform android --local
eas build:run -p ios # select expo build from above
eas build:run -p android # select expo build from above
npx expo start --dev-client
6 changes: 3 additions & 3 deletions app.config.js
Original file line number Diff line number Diff line change
@@ -42,7 +42,7 @@ switch (variant) {
export default {
name: name,
slug: 'scorepad',
version: "2.4.4",
version: "2.4.5",
orientation: "default",
icon: icon,
assetBundlePatterns: [
@@ -53,7 +53,7 @@ export default {
bundleIdentifier: packageName,
supportsTablet: true,
requireFullScreen: false,
buildNumber: "65",
buildNumber: "66",
infoPlist: {
RCTAsyncStorageExcludeFromBackup: false
},
@@ -67,7 +67,7 @@ export default {
},
package: packageName,
permissions: [],
versionCode: 65,
versionCode: 66,
googleServicesFile: "./google-services.json",
},
userInterfaceStyle: "dark",
2 changes: 1 addition & 1 deletion eas.json
Original file line number Diff line number Diff line change
@@ -51,4 +51,4 @@
}
}
}
}
}
72 changes: 72 additions & 0 deletions google-services.json
Original file line number Diff line number Diff line change
@@ -41,6 +41,78 @@
]
}
}
},
{
"client_info": {
"mobilesdk_app_id": "1:774305501031:android:eab18897bfe9d4fbf7e9c2",
"android_client_info": {
"package_name": "com.wyne.scorepad.dev"
}
},
"oauth_client": [
{
"client_id": "774305501031-c5ceh2ekgjqc4n9o0at9j2e83d162mpb.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyBi8wD4wlmaEiDh57iLFqQcqPlUl6nZjrw"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": [
{
"client_id": "774305501031-c5ceh2ekgjqc4n9o0at9j2e83d162mpb.apps.googleusercontent.com",
"client_type": 3
},
{
"client_id": "774305501031-4p2p095nnknm4b2vh41q36l5inespraj.apps.googleusercontent.com",
"client_type": 2,
"ios_info": {
"bundle_id": "com.wyne.scorepad"
}
}
]
}
}
},
{
"client_info": {
"mobilesdk_app_id": "1:774305501031:android:ac86740f897e2a32f7e9c2",
"android_client_info": {
"package_name": "com.wyne.scorepad.preview"
}
},
"oauth_client": [
{
"client_id": "774305501031-c5ceh2ekgjqc4n9o0at9j2e83d162mpb.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyBi8wD4wlmaEiDh57iLFqQcqPlUl6nZjrw"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": [
{
"client_id": "774305501031-c5ceh2ekgjqc4n9o0at9j2e83d162mpb.apps.googleusercontent.com",
"client_type": 3
},
{
"client_id": "774305501031-4p2p095nnknm4b2vh41q36l5inespraj.apps.googleusercontent.com",
"client_type": 2,
"ios_info": {
"bundle_id": "com.wyne.scorepad"
}
}
]
}
}
}
],
"configuration_version": "1"
8,002 changes: 3,600 additions & 4,402 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -50,7 +50,7 @@
"react": "18.2.0",
"react-dom": "18.2.0",
"react-moment": "^1.1.3",
"react-native": "0.72.5",
"react-native": "0.72.6",
"react-native-animated-pagination-dots": "^0.1.73",
"react-native-elements": "^3.4.2",
"react-native-gesture-handler": "~2.12.0",
20 changes: 17 additions & 3 deletions redux/GamesSlice.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import analytics from '@react-native-firebase/analytics';
import { createSlice, PayloadAction , createEntityAdapter , createAsyncThunk } from '@reduxjs/toolkit';
import { createSlice, PayloadAction, createEntityAdapter, createAsyncThunk, createSelector } from '@reduxjs/toolkit';
import * as Crypto from 'expo-crypto';

import { playerAdd } from './PlayersSlice';
import { playerAdd, selectAllPlayers } from './PlayersSlice';
import { setCurrentGameId } from './SettingsSlice';
import { RootState } from './store';

export interface GameState {
id: string;
@@ -101,12 +102,25 @@ export const asyncCreateGame = createAsyncThunk(
}
);

export const selectSortedPlayers = createSelector(
[
selectAllPlayers,
(state: RootState) => state.games.entities[state.settings.currentGameId]
],
(players, currentGame) => players
.filter(player => currentGame?.playerIds.includes(player.id))
.sort((a, b) => {
if (currentGame?.playerIds == undefined) return 0;
return currentGame.playerIds.indexOf(a.id) - currentGame.playerIds.indexOf(b.id);
})
);

export const {
updateGame,
roundNext,
roundPrevious,
gameSave,
gameDelete
gameDelete,
} = gamesSlice.actions;

export default gamesSlice.reducer;
6 changes: 3 additions & 3 deletions redux/PlayersSlice.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import crashlytics from '@react-native-firebase/crashlytics';
import { createSlice, PayloadAction , createEntityAdapter } from '@reduxjs/toolkit';
import { createSlice, PayloadAction, createEntityAdapter } from '@reduxjs/toolkit';

type RoundIndex = number;

@@ -37,9 +37,9 @@ const scoresSlice = createSlice({
const multiplier = action.meta.multiplier;

if (typeof scores[round] !== 'number') {
scores[round] = 0;
scores[round] = Number(scores[round]) || 0;
}
scores[round] += multiplier;
scores[round] += Number(multiplier);
} catch (error) {
const err = error as Error;
crashlytics().recordError(err);
15 changes: 12 additions & 3 deletions src/components/Buttons/CheckButton.test.tsx
Original file line number Diff line number Diff line change
@@ -8,11 +8,20 @@ import CheckButton from './CheckButton';
describe('CheckButton', () => {
const navigation = useNavigationMock();

it('should navigate back a screen when pressed', async () => {
const { getByRole } = render(<CheckButton navigation={navigation} />);
it.skip('should navigate to Game screen when pressed', async () => {
const { getByRole } = render(<CheckButton navigation={navigation} route={{ key: "Settings", name: "Settings", params: { reason: "new_game" } }} />);
const button = getByRole('button');
await waitFor(() => {
fireEvent.press(button);
expect(navigation.navigate).toHaveBeenCalledWith("Game");
});
});

it.skip('should navigate back a screen when pressed', async () => {
const { getByRole } = render(<CheckButton navigation={navigation} route={{ key: "Settings", name: "Settings", params: { reason: "" } }} />);
const button = getByRole('button');
fireEvent.press(button);
await waitFor(() => {
fireEvent.press(button);
expect(navigation.goBack).toHaveBeenCalled();
});
});
7 changes: 6 additions & 1 deletion src/components/GameListItem.tsx
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@ import { NativeStackNavigationProp } from '@react-navigation/native-stack';
import { AnyAction, ThunkDispatch } from '@reduxjs/toolkit';
import Moment from 'react-moment';
import { Text, StyleSheet, Alert, Platform } from 'react-native';
import { ListItem , Icon } from 'react-native-elements';
import { ListItem, Icon } from 'react-native-elements';
import Animated, { FadeInUp, SlideOutLeft } from 'react-native-reanimated';

import { selectGameById, gameDelete } from '../../redux/GamesSlice';
@@ -146,6 +146,11 @@ const GameListItem: React.FunctionComponent<Props> = ({ navigation, gameId, inde
},
];

// If platform is android, remove the action with id 'share'
if (Platform.OS === 'android') {
actions.splice(1, 1);
}

type MenuActionHandler = (eativeEvent: NativeActionEvent) => void;

/**
7 changes: 2 additions & 5 deletions src/components/ScoreLog/PlayerNameColumn.tsx
Original file line number Diff line number Diff line change
@@ -3,9 +3,8 @@ import React from 'react';
import { Text, View, StyleSheet } from 'react-native';
import { Icon } from 'react-native-elements/dist/icons/Icon';

import { selectGameById } from '../../../redux/GamesSlice';
import { selectGameById, selectSortedPlayers } from '../../../redux/GamesSlice';
import { useAppSelector } from '../../../redux/hooks';
import { selectAllPlayers } from '../../../redux/PlayersSlice';
import { palette, systemBlue } from '../../constants';

const PlayerNameColumn: React.FunctionComponent = ({ }) => {
@@ -14,9 +13,7 @@ const PlayerNameColumn: React.FunctionComponent = ({ }) => {

if (currentGame == undefined) return null;

const players = useAppSelector(state => selectAllPlayers(state)
.filter(player => currentGame.playerIds.includes(player.id))
).sort((a, b) => currentGame.playerIds.indexOf(a.id) - currentGame.playerIds.indexOf(b.id));
const players = useAppSelector(selectSortedPlayers);

return (
<View style={{ paddingVertical: 10 }}>
24 changes: 17 additions & 7 deletions src/components/Sheets/AddendModal.tsx
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@ import React, { useCallback, useMemo } from 'react';

import { BottomSheetBackdrop, BottomSheetBackdropProps, BottomSheetModal } from '@gorhom/bottom-sheet';
import { Picker } from '@react-native-picker/picker';
import { View, StyleSheet, Text } from 'react-native';
import { View, StyleSheet, Text, Platform } from 'react-native';

import { useAppDispatch, useAppSelector } from '../../../redux/hooks';
import { setAddendOne, setAddendTwo, setMultiplier } from '../../../redux/SettingsSlice';
@@ -17,10 +17,12 @@ const AddendModal: React.FunctionComponent<Props> = ({ }) => {
const addendTwo = useAppSelector(state => state.settings.addendTwo);

// Array of 1 to 50
const addendOptions = Array.from({ length: 50 }, (_, i) => i + 1);
const addendOptions = Array.from({ length: 100 }, (_, i) => i + 1);

const dispatch = useAppDispatch();

const isAndroid = useMemo(() => Platform.OS === 'android', []);

const onTapValueChange = useCallback((itemValue: number, itemIndex: number) => {
dispatch(setMultiplier(addendOptions[itemIndex]));
dispatch(setAddendOne(addendOptions[itemIndex]));
@@ -77,11 +79,11 @@ const AddendModal: React.FunctionComponent<Props> = ({ }) => {
}}>
<View>
<Text style={{ color: 'white', textAlign: 'center' }}>Single Tap</Text>
<View style={styles.pickerContainer}>
<View style={isAndroid ? styles.pickerContainerAndroid : styles.pickerContainer}>
<Picker
selectedValue={addendOne}
onValueChange={onTapValueChange}
style={styles.picker}
style={isAndroid ? styles.pickerAndroid : styles.picker}
itemStyle={styles.pickerItem}
>
{
@@ -95,11 +97,11 @@ const AddendModal: React.FunctionComponent<Props> = ({ }) => {

<View>
<Text style={{ color: 'white', textAlign: 'center' }}>Long Press</Text>
<View style={styles.pickerContainer}>
<View style={isAndroid ? styles.pickerContainerAndroid : styles.pickerContainer}>
<Picker
selectedValue={addendTwo}
onValueChange={onLongTapValueChange}
style={styles.picker}
style={isAndroid ? styles.pickerAndroid : styles.picker}
itemStyle={styles.pickerItem}
>
{
@@ -123,7 +125,10 @@ const styles = StyleSheet.create({
alignItems: 'center',
},
picker: {
width: 80,
width: 90,
},
pickerAndroid: {
width: 120,
},
pickerItem: {
color: 'white',
@@ -134,6 +139,11 @@ const styles = StyleSheet.create({
borderRadius: 10,
margin: 10,
},
pickerContainerAndroid: {
backgroundColor: 'white',
borderRadius: 10,
margin: 10,
},
});

export default AddendModal;
27 changes: 12 additions & 15 deletions src/components/Sheets/GameSheet.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import React, { useCallback, useMemo, useState } from 'react';

import BottomSheet, { BottomSheetBackdrop, BottomSheetBackdropProps, BottomSheetScrollView } from '@gorhom/bottom-sheet';
import { ParamListBase , useIsFocused } from '@react-navigation/native';
import { ParamListBase, useIsFocused } from '@react-navigation/native';
import { NativeStackNavigationProp } from '@react-navigation/native-stack';
import { View, StyleSheet, Text, Alert , TouchableWithoutFeedback } from 'react-native';
import { View, StyleSheet, Text, Alert, TouchableWithoutFeedback, Platform } from 'react-native';
import { Button } from 'react-native-elements';
import Animated, { Extrapolate, FadeIn, Layout, interpolate, useAnimatedStyle, useSharedValue } from 'react-native-reanimated';
import { SafeAreaView } from 'react-native-safe-area-context';

import { selectGameById, updateGame } from '../../../redux/GamesSlice';
import { selectGameById, selectSortedPlayers, updateGame } from '../../../redux/GamesSlice';
import { useAppDispatch, useAppSelector } from '../../../redux/hooks';
import { selectAllPlayers, updatePlayer } from '../../../redux/PlayersSlice';
import { updatePlayer } from '../../../redux/PlayersSlice';
import { systemBlue } from '../../constants';
import BigButton from '../BigButtons/BigButton';
import Rounds from '../Rounds';
@@ -38,12 +38,7 @@ const GameSheet: React.FunctionComponent<Props> = ({ navigation, containerHeight

if (currentGame == undefined) return null;

const players = useAppSelector(state => selectAllPlayers(state)
.filter(player => currentGame?.playerIds.includes(player.id))
).sort((a, b) => {
if (currentGame?.playerIds == undefined) return 0;
return currentGame.playerIds.indexOf(a.id) - currentGame.playerIds.indexOf(b.id);
});
const players = useAppSelector(selectSortedPlayers);

// ref
const gameSheetRef = useGameSheetContext();
@@ -231,11 +226,13 @@ const GameSheet: React.FunctionComponent<Props> = ({ navigation, containerHeight
https://github.com/software-mansion/react-native-reanimated/issues/4822
*/}
<Animated.View key={isFocused + ''} layout={Layout.delay(200)} style={{ flexDirection: 'row', justifyContent: 'space-around', paddingVertical: 10 }}>
<BigButton text="Share"
color={systemBlue}
icon="share-outline"
onPress={() => navigation.navigate('Share')}
/>
{Platform.OS === 'ios' &&
<BigButton text="Share"
color={systemBlue}
icon="share-outline"
onPress={() => navigation.navigate('Share')}
/>
}

<Animated.View layout={Layout.delay(200)} style={{ justifyContent: 'center', alignItems: 'center' }}>
{!currentGame.locked &&

0 comments on commit 67c8ca2

Please sign in to comment.