From 0a6b80c9fa33d5bf97be89c3d2f8c46165e39fa4 Mon Sep 17 00:00:00 2001 From: Justin Wyne <1986068+wyne@users.noreply.github.com> Date: Mon, 25 Dec 2023 11:57:34 -0500 Subject: [PATCH 001/150] Store Review dependencies --- package-lock.json | 27 +++++++++++++++++++++++++++ package.json | 4 +++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index 052449bf..0e56375a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -35,11 +35,13 @@ "expo-device": "~5.4.0", "expo-haptics": "~12.4.0", "expo-image": "~1.3.2", + "expo-linking": "~5.0.2", "expo-screen-orientation": "~6.0.5", "expo-sensors": "~12.3.0", "expo-sharing": "~11.5.0", "expo-splash-screen": "~0.20.5", "expo-status-bar": "~1.6.0", + "expo-store-review": "~6.4.0", "expo-system-ui": "~2.4.0", "expo-updates": "~0.18.12", "firebase": "^9.17.1", @@ -8047,6 +8049,11 @@ "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.11.tgz", "integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==" }, + "node_modules/@types/qs": { + "version": "6.9.11", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.11.tgz", + "integrity": "sha512-oGk0gmhnEJK4Yyk+oI7EfXsLayXatCWPHary1MtcmbAifkobT9cM9yutG/hZKIseOU0MqbIwQ/u2nn/Gb+ltuQ==" + }, "node_modules/@types/react": { "version": "18.2.45", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.45.tgz", @@ -11970,6 +11977,18 @@ "expo": "*" } }, + "node_modules/expo-linking": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/expo-linking/-/expo-linking-5.0.2.tgz", + "integrity": "sha512-SPQus0+tYGx9c69Uw4wmdo3rkKX8vRT1vyJz/mvkpSlZN986s0NmP/V0M5vDv5Zv2qZzVdqJyuITFe0Pg5aI+A==", + "dependencies": { + "@types/qs": "^6.9.7", + "expo-constants": "~14.4.2", + "invariant": "^2.2.4", + "qs": "^6.11.0", + "url-parse": "^1.5.9" + } + }, "node_modules/expo-manifests": { "version": "0.7.2", "resolved": "https://registry.npmjs.org/expo-manifests/-/expo-manifests-0.7.2.tgz", @@ -12186,6 +12205,14 @@ "resolved": "https://registry.npmjs.org/expo-status-bar/-/expo-status-bar-1.6.0.tgz", "integrity": "sha512-e//Oi2WPdomMlMDD3skE4+1ZarKCJ/suvcB4Jo/nO427niKug5oppcPNYO+csR6y3ZglGuypS+3pp/hJ+Xp6fQ==" }, + "node_modules/expo-store-review": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/expo-store-review/-/expo-store-review-6.4.0.tgz", + "integrity": "sha512-aD06KSOO9syeecaP9NfJO++FzmfQjg49HY7qeUQ9r826YqswW/FPAcnXY0RJLhfJTqeAPRSl/xzPLZA5vwdqLQ==", + "peerDependencies": { + "expo": "*" + } + }, "node_modules/expo-structured-headers": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/expo-structured-headers/-/expo-structured-headers-3.3.0.tgz", diff --git a/package.json b/package.json index 513429c9..4d69627d 100644 --- a/package.json +++ b/package.json @@ -71,7 +71,9 @@ "react-redux": "^8.0.2", "redux-persist": "^6.0.0", "semver": "^7.5.4", - "typescript": "^5.1.6" + "typescript": "^5.1.6", + "expo-store-review": "~6.4.0", + "expo-linking": "~5.0.2" }, "devDependencies": { "@babel/core": "^7.19.3", From 1116f2d6af26574e9e3eeaf4ecac4c98bd8b9190 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jan 2024 09:17:26 +0000 Subject: [PATCH 002/150] Bump moment from 2.29.4 to 2.30.1 Bumps [moment](https://github.com/moment/moment) from 2.29.4 to 2.30.1. - [Changelog](https://github.com/moment/moment/blob/develop/CHANGELOG.md) - [Commits](https://github.com/moment/moment/compare/2.29.4...2.30.1) --- updated-dependencies: - dependency-name: moment dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 872c9a8f..3b2c62f8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -44,7 +44,7 @@ "expo-updates": "~0.18.12", "firebase": "^9.17.1", "lodash": "^4.17.21", - "moment": "^2.29.4", + "moment": "^2.30.1", "react": "18.2.0", "react-dom": "18.2.0", "react-moment": "^1.1.3", @@ -18130,9 +18130,9 @@ } }, "node_modules/moment": { - "version": "2.29.4", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", - "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", "engines": { "node": "*" } diff --git a/package.json b/package.json index fc366adf..d96db17c 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "expo-updates": "~0.18.12", "firebase": "^9.17.1", "lodash": "^4.17.21", - "moment": "^2.29.4", + "moment": "^2.30.1", "react": "18.2.0", "react-dom": "18.2.0", "react-moment": "^1.1.3", From 2f176de22ac2ead22f7bf7093c91eda437ac2611 Mon Sep 17 00:00:00 2001 From: Justin Wyne <1986068+wyne@users.noreply.github.com> Date: Thu, 21 Mar 2024 19:36:24 -0700 Subject: [PATCH 003/150] Better swipe analytics --- src/components/Interactions/Swipe/Swipe.tsx | 32 ++++++++++++++------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/src/components/Interactions/Swipe/Swipe.tsx b/src/components/Interactions/Swipe/Swipe.tsx index 314ab719..a88a405e 100644 --- a/src/components/Interactions/Swipe/Swipe.tsx +++ b/src/components/Interactions/Swipe/Swipe.tsx @@ -17,6 +17,8 @@ interface HalfTapProps { playerId: string; } +const notchSize = 50; + const SwipeVertical: React.FC = ({ children, index, @@ -47,6 +49,12 @@ const SwipeVertical: React.FC = ({ powerHoldRef.current = powerHold; }, [powerHold]); + useEffect(() => { + return () => { + clearTimeout(powerHoldTimer); + }; + }, []); + const scale = holdDuration.interpolate({ inputRange: [0, powerHoldTime * .9, powerHoldTime], outputRange: [1, 1.1, 1.05], @@ -151,6 +159,17 @@ const SwipeVertical: React.FC = ({ // Handle the end of the gesture totalOffset.value = null; + analytics().logEvent('score_change', { + player_index: index, + game_id: currentGameId, + addend: powerHold ? addendOne : addendTwo, + round: roundCurrent, + type: event.nativeEvent.translationY > 0 ? 'decrement' : 'increment', + powerHold: powerHold, + notches: Math.round((event.nativeEvent.translationY || 0) / notchSize), + interaction: 'swipe-vertical', + }); + // Spring the animation back to the start Animated.spring(pan, { toValue: { x: 0, y: 0 }, @@ -177,15 +196,6 @@ const SwipeVertical: React.FC = ({ Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light); } - analytics().logEvent('score_change', { - player_index: index, - game_id: currentGameId, - addend: Math.abs(a), - round: roundCurrent, - type: a > 0 ? 'increment' : 'decrement', - interaction: 'swipe-vertical', - }); - dispatch(playerRoundScoreIncrement(playerId, roundCurrent, a)); }; @@ -196,8 +206,8 @@ const SwipeVertical: React.FC = ({ (currentValue, previousValue) => { if (currentValue === null) return; - const c = Math.round((currentValue || 0) / 50); - const p = Math.round((previousValue || 0) / 50); + const c = Math.round((currentValue || 0) / notchSize); + const p = Math.round((previousValue || 0) / notchSize); if (c - p !== 0) { runOnJS(scoreChangeHandler)(c - p); } From 3ad6dfce26a5cf8be7f80a4053273e723cb710da Mon Sep 17 00:00:00 2001 From: Justin Wyne <1986068+wyne@users.noreply.github.com> Date: Thu, 21 Mar 2024 20:03:16 -0700 Subject: [PATCH 004/150] Player Index --- redux/SettingsSlice.ts | 10 ++++++-- redux/store.ts | 1 + src/components/Boards/FlexboxTile.tsx | 9 ++++++-- .../PlayerTiles/PlayerIndexLabel.tsx | 23 +++++++++++++++++++ src/screens/AppInfoScreen.tsx | 15 ++++++++---- 5 files changed, 50 insertions(+), 8 deletions(-) create mode 100644 src/components/PlayerTiles/PlayerIndexLabel.tsx diff --git a/redux/SettingsSlice.ts b/redux/SettingsSlice.ts index eb9cc287..0f18c616 100644 --- a/redux/SettingsSlice.ts +++ b/redux/SettingsSlice.ts @@ -12,6 +12,7 @@ export interface SettingsState { currentGameId: string | undefined; onboarded: string | undefined; showPointParticles: boolean; + showPlayerIndex: boolean; interactionType: InteractionType; }; @@ -23,6 +24,7 @@ const initialState: SettingsState = { currentGameId: undefined, onboarded: undefined, showPointParticles: true, + showPlayerIndex: false, interactionType: InteractionType.SwipeVertical, }; @@ -36,9 +38,12 @@ const settingsSlice = createSlice({ toggleHomeFullscreen(state) { state.home_fullscreen = !state.home_fullscreen; }, - toggleshowPointParticles(state) { + toggleShowPointParticles(state) { state.showPointParticles = !state.showPointParticles; }, + toggleShowPlayerIndex(state) { + state.showPlayerIndex = !state.showPlayerIndex; + }, setMultiplier(state, action: PayloadAction) { state.multiplier = action.payload; }, @@ -66,7 +71,8 @@ export const { setAddendOne, setAddendTwo, setOnboardedVersion, - toggleshowPointParticles, + toggleShowPointParticles, + toggleShowPlayerIndex, setInteractionType, } = settingsSlice.actions; diff --git a/redux/store.ts b/redux/store.ts index b3aadeea..b4aeaf94 100644 --- a/redux/store.ts +++ b/redux/store.ts @@ -18,6 +18,7 @@ const settingsPersistConfig = { 'currentGameId', 'onboarded', 'showPointParticles', + 'showPlayerIndex', 'interactionType', ], }; diff --git a/src/components/Boards/FlexboxTile.tsx b/src/components/Boards/FlexboxTile.tsx index 3b8df2bd..ba62fe00 100644 --- a/src/components/Boards/FlexboxTile.tsx +++ b/src/components/Boards/FlexboxTile.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import { DimensionValue, StyleSheet } from 'react-native'; +import { DimensionValue, StyleSheet, Text, View } from 'react-native'; import Animated, { Easing, FadeIn } from 'react-native-reanimated'; import { selectGameById } from '../../../redux/GamesSlice'; @@ -9,6 +9,7 @@ import { selectInteractionType } from '../../../redux/selectors'; import { interactionComponents } from '../Interactions/InteractionComponents'; import { InteractionType } from '../Interactions/InteractionType'; import AdditionTile from '../PlayerTiles/AdditionTile/AdditionTile'; +import PlayerIndexLabel from '../PlayerTiles/PlayerIndexLabel'; interface Props { index: number; @@ -39,6 +40,8 @@ const FlexboxTile: React.FunctionComponent = ({ const currentGame = useAppSelector(state => selectGameById(state, currentGameId)); if (typeof currentGame == 'undefined') return null; + const playerIndexLabel = useAppSelector(state => state.settings.showPlayerIndex); + const widthPerc: DimensionValue = `${(100 / cols)}%`; const heightPerc: DimensionValue = `${(100 / rows)}%`; @@ -54,8 +57,10 @@ const FlexboxTile: React.FunctionComponent = ({ { backgroundColor: color, width: widthPerc, - height: heightPerc + height: heightPerc, + borderBottomLeftRadius: playerIndexLabel ? 7 : undefined, }]}> + = ({ index, fontColor, enabled }) => { + if (!enabled) return null; + + return ( + + + {index + 1} + + + ); +}; + +export default PlayerIndexLabel; diff --git a/src/screens/AppInfoScreen.tsx b/src/screens/AppInfoScreen.tsx index 5c64d3ad..3c745f44 100644 --- a/src/screens/AppInfoScreen.tsx +++ b/src/screens/AppInfoScreen.tsx @@ -4,11 +4,11 @@ import analytics from '@react-native-firebase/analytics'; import { NativeStackNavigationProp } from '@react-navigation/native-stack'; import { ParamListBase } from '@react-navigation/routers'; import * as Application from 'expo-application'; -import { Text, View, StyleSheet, Alert, ScrollView, Linking, Platform, Switch } from 'react-native'; +import { Alert, Linking, Platform, ScrollView, StyleSheet, Switch, Text, View } from 'react-native'; import { Button } from 'react-native-elements'; import { useAppDispatch, useAppSelector } from '../../redux/hooks'; -import { toggleshowPointParticles } from '../../redux/SettingsSlice'; +import { toggleShowPlayerIndex, toggleShowPointParticles } from '../../redux/SettingsSlice'; import RotatingIcon from '../components/AppInfo/RotatingIcon'; interface Props { @@ -40,8 +40,11 @@ const AppInfoScreen: React.FunctionComponent = ({ navigation }) => { const appVersion = Application.nativeApplicationVersion; const showPointParticles = useAppSelector(state => state.settings.showPointParticles); + const showPlayerIndex = useAppSelector(state => state.settings.showPlayerIndex); + const dispatch = useAppDispatch(); - const toggleSwitch = () => { dispatch(toggleshowPointParticles()); }; + const toggleParticleSwitch = () => { dispatch(toggleShowPointParticles()); }; + const togglePlayerIndexSwitch = () => { dispatch(toggleShowPlayerIndex()); }; const alertWithVersion = async () => { Alert.alert(`ScorePad with Rounds\n` + @@ -67,7 +70,11 @@ const AppInfoScreen: React.FunctionComponent = ({ navigation }) => {
- + + + + +
From ea24029e5e05a07ec90021e8875ff37937b4ba0b Mon Sep 17 00:00:00 2001 From: Justin Wyne <1986068+wyne@users.noreply.github.com> Date: Sat, 23 Mar 2024 00:03:21 -0700 Subject: [PATCH 005/150] Fix picker for android --- src/components/Sheets/AddendModal.tsx | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/components/Sheets/AddendModal.tsx b/src/components/Sheets/AddendModal.tsx index bd18794c..db1c3948 100644 --- a/src/components/Sheets/AddendModal.tsx +++ b/src/components/Sheets/AddendModal.tsx @@ -3,6 +3,7 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { BottomSheetBackdrop, BottomSheetBackdropProps, BottomSheetModal, BottomSheetScrollView } from '@gorhom/bottom-sheet'; import { Picker } from '@react-native-picker/picker'; import * as ScreenOrientation from 'expo-screen-orientation'; +import { debounce } from 'lodash'; import { Platform, StyleSheet, Text, View } from 'react-native'; import { useAppDispatch, useAppSelector } from '../../../redux/hooks'; @@ -59,11 +60,15 @@ const AddendModal: React.FunctionComponent = ({ }) => { // TODO: analytics }, [addendOne]); + const debouncedTapValueChange = debounce(onTapValueChange, 200); + const onLongTapValueChange = useCallback((itemValue: number) => { dispatch(setAddendTwo(itemValue)); // TODO: analytics }, [addendTwo]); + const debouncedLongTapValueChange = debounce(onLongTapValueChange, 200); + // ref const addendModalRef = useAddendModalContext(); @@ -146,7 +151,7 @@ const AddendModal: React.FunctionComponent = ({ }) => { @@ -164,7 +169,7 @@ const AddendModal: React.FunctionComponent = ({ }) => { From 3946cecc0a97a5de5e09f9a037b117ca6339f46e Mon Sep 17 00:00:00 2001 From: Justin Wyne <1986068+wyne@users.noreply.github.com> Date: Sat, 23 Mar 2024 00:21:41 -0700 Subject: [PATCH 006/150] Fix powerHold for Android --- src/components/Interactions/Swipe/Swipe.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/components/Interactions/Swipe/Swipe.tsx b/src/components/Interactions/Swipe/Swipe.tsx index 7fc15223..d8198cef 100644 --- a/src/components/Interactions/Swipe/Swipe.tsx +++ b/src/components/Interactions/Swipe/Swipe.tsx @@ -136,9 +136,10 @@ const SwipeVertical: React.FC = ({ // Handle the gesture movement // Invert the value for panning up to be positive - totalOffset.value = -event.nativeEvent.translationY; + const y = event.nativeEvent.translationY; + totalOffset.value = -y; - if (powerHoldRef.current == false) { + if (powerHoldRef.current == false && Math.abs(y) > 1) { powerHoldStop(); } }, From be3c5ec3b9d069da04d0d9652b6400e5e52bd27c Mon Sep 17 00:00:00 2001 From: Justin Wyne <1986068+wyne@users.noreply.github.com> Date: Sat, 23 Mar 2024 00:48:09 -0700 Subject: [PATCH 007/150] android dev icons --- app.config.js | 21 +++++++++++++++++++-- assets/adaptive-icon-bg-dev.png | Bin 0 -> 8016 bytes assets/adaptive-icon-bg-preview.png | Bin 0 -> 4700 bytes assets/adaptive-icon-dev.png | Bin 0 -> 56739 bytes assets/adaptive-icon-preview.png | Bin 0 -> 79588 bytes 5 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 assets/adaptive-icon-bg-dev.png create mode 100644 assets/adaptive-icon-bg-preview.png create mode 100644 assets/adaptive-icon-dev.png create mode 100644 assets/adaptive-icon-preview.png diff --git a/app.config.js b/app.config.js index 3927d48d..f52ae147 100644 --- a/app.config.js +++ b/app.config.js @@ -39,6 +39,23 @@ switch (variant) { break; } +let androidIcon; +let androidIconBg; +switch (variant) { + case "development": + androidIcon = "./assets/adaptive-icon-dev.png"; + androidIconBg = "./assets/adaptive-icon-bg-dev.png"; + break; + case "preview": + androidIcon = "./assets/adaptive-icon-preview.png"; + androidIconBg = "./assets/adaptive-icon-bg-preview.png"; + break; + default: + androidIcon = "./assets/adaptive-icon.png"; + androidIconBg = "./assets/adaptive-icon-bg.png"; + break; +} + export default { name: name, slug: "scorepad", @@ -58,10 +75,10 @@ export default { googleServicesFile: "./GoogleService-Info.plist", }, android: { - icon: "./assets/adaptive-icon.png", + icon: androidIcon, adaptiveIcon: { foregroundImage: "./assets/adaptive-icon-fg.png", - backgroundImage: "./assets/adaptive-icon-bg.png", + backgroundImage: androidIconBg, }, package: packageName, permissions: [], diff --git a/assets/adaptive-icon-bg-dev.png b/assets/adaptive-icon-bg-dev.png new file mode 100644 index 0000000000000000000000000000000000000000..bc5ace27d9c0512221accda8dd1349c20d90cb59 GIT binary patch literal 8016 zcmeHKYgAKL7QXjFEH5n&izu&diAA-(9C~%A*>rvMi<5<*ZN(QKYFBP$zlKCrm62A!W4`xq2 zE#&Ag8s*q?X$+BD{4yq{joxT21P|-BKCAB?<<^v?SqnswizQKQmYqLW2^)U`)Jb(x^~G_*MulE{aQCE67Nq z1~U8@ezZ^rX#$2{+ z36NNlnavk&7cJpu(n%%H^@Js5?#xI{7p4mMR6_6e9fJMB5E_jz^x{XZQ<$3kizR;M zlv}_-Ch>*2l;OvGp&LwP5pRQIGE$R(WkP@GQWli_pLbJsSWLqBe=Uae6ut$nhT5>0 zFK7$3nVazVB?NItBEwd15}^Za@qGH`la`79T30+{Vvr*8Z7k^e@&c z(7xgm7whFu7O>HflVLsA_tl;$pLJozkWtFZGio)$v08z7cr~v4iZVI+Q*on;ZO$3f zxA0q`0aixF$`4ry3(5-+d)wxj% zweaoK5xZUq?@?oFgHEA4S*`v;{B&3$E;WsuHuf8T5(kPO?b96oX5)s-Vowxn!}2Wd zDLgfV<2WabgC4vzZ#`UdC2(=j6cG*q4YT1C{KzH9qTX8~M}*q&U>nH;IEZ8R+n0X;i4ofRAZ_DEk3bM+IUBe7>=Q_ld@Bd-Z7&u=K&8o%u(+A? zA!lvCq9N}r9RdfGLcOua2eQ`-wx`lScZcAhl@H?Z=32O=oU1tY+guSn5ce5#+QnU7 z>fCdU$1Y2&7k>F6WKPOEKX^5nzw_L3qe6=0C*-%;D(gOrZhSVfb)n>ff;K!8%W@F) z*A{23Z1u9VYO)^n#Vb!(g+cO0fGh2-)}+JH9Q4B0Lmbj!rX1-iDkWp2576>Qo6@<6Z;BUieDeo)aH>1mDeR(qX>T=BHL zvIUT>wKhJ;+VZH~Fa|G0anRNtbt(jYXK~E0>p=l2_Yjc!=a_U!_n<+oYj7%}U#d_B zM2*i1C_?hRK#qE~EC_(P(7Hg5?A7T=;1b)J`fZc%n)8zRva;GI|B#KnIZO7PHXU&E zxiet$$6X#&zZ(2T;N+|}T=^zSN&HN%CMzS3*(mW1PN(1w?R|xdT(Nn(3<5hJIbwG$ z;3z5gN1rr#0`OQ-qjvS2(`nqdD#npIRD)wfHAS0YF;s2`AF<={KsJS z=)r2<_KzXK@5z*h0c#9!H)QbFfzvYvlyQ3oaXW-bG62t zXgB}*`uk_@%9p78>Shy1u&w39j70RI53{GC#lInM16uW^69Q0sa+j|f#w&xV`XG0< zl9~8DSk#%crd$$XAenyMF^$8A=N36GSiZusnP_01f+ak~cTXi8Sh!2t&JnVIaR-{+ z?TcVfhn=xz6*-G4s@1yeir2GBbqXi_>S%A*0SPSR_rxr9+zvfU!R8Ul-W{lmDn|RB$=X&wb zu#X|9Aifd=XdR$3DZ2eN=*ldR*lv4D8D!*~1kqP_y83-Ga@KchxL33By3;Ck%GHhL zHhrD0%so%e^mtrWoPOKF6j5oDe+@JZHxIc(!Ys#t=9o#wWugk^fx7<0aYS6dS-$uk{GZ7_gK9c$GS@hN77%6yvLv!zAGcKvza z{r(n)szG~wa$-b3p^#?xwD5E5Rojvk(xklH$!m|syQ}9{@RE6|YjFt@L0N8yU@~V? zrB{^8s=)V&W&I;YJzITW>ZVicZg-o^d3vq6RCbEZsEALV81K^r$RwtHr2}K*Eiy^h zseZNEPP$EJQ16xIv}mjJ#{GrGEc3Fj#fF;Dlm=b-948b-hvQe{xq%sJUCGYti0qrT5oecH%Mb ztTb0l_DiyJXho-B2H>0`rLIHYbknf_MuvR^=$RwqFO#W#5y!ZdF8_ozloQKABl)l` z&Q7+9yfL9zE@pmt_rXnze!iE|jeuX|YtdolYZBl25660P A8vp1sReYN)f;N zIqTl_JO91+f8CQi6BFh>vG@r90Or26`OPE%m=U<00n7>s4EIPqp1?3WcXKix0KyjB zzk-13ns5Mkdfr=aZrDw#8P#pbH+H`(zLis*{1uNkN?B)JD6^QkJt!%0( z{7(K}@Z6rm!1j;JS9)le-loqw;~BG)ZsTSN-kxTmrfzXlx@}t;3H2&!=K*P^HdCrZ z+Qy|unbx3e+a-u1yuTt^U?ZWu>|S3sThN??_Vb8Sw|E!WS1P^iRpQLl>BTDSsA{c; zbVQ?;PEwhJlLE(xu8dkIFrI>XB5J)1yHY{+X$;*o{~&x2<@2bLd_HHAwJ2&rR+ETA z3HKv$kwq7FE#kXo0tU@p(kx(1Hwyq}y$Ar$eF^|a*9WM~sEu-q27&-lhz$VNe{q@? z5)4d`LIV$GKUnDx3(UyB3|;4)Ny>_xdT~9)3lBckb!GAk+NOaj{0`4MzIFegsNC%s z5ErG1U2H#UG_=a0X+*VI?|`iK=;QVqwpJn^B#eUoOt~Oko8LT0?MV@1EOA|TcXtm? z^f$TISX{j|1wQ1|c7>T-FmQ0}gE-Hg8)emt?3*#SG-%NYC9mV-I_Ny)`v}kFw}Iwi zl#T0vIq_#EUQkb(Kpm37!^PlH93r!U6I(1YbZ`Wt#fP;X*WqlIt{~iV9-d1KL%@~> z0qdU&0)S(|01*5%06e+*2LS#hv;G6X^}7uJ_o={u{SgKa0Y2pPfart3b#lQ0&{3G~ zqy!7U#y#U2iqRJH;gf5_Q=EDJOeYsU*)<)$6JxVv(v`^<;2PYzjS^Q1w#pN^5S&}q z!sSpPyMB~l!mS1F97EeK))jP8v<)k`Il2Hy&Oor(G(@iFTQfM z?P@i3PLZ_zgnfr}`T{icnv2(05R-mSM02E5gr$uMRbH*&OeR8H9ANGB1NG z5<_Y|r5VH**!T%vT_OG09L)0pjgMIM49sTkX_q=%X#kjFJ zhkZW1z}421LKOF;U{pmbIps;}vSafpNbQQP(I~|x5lz<@>%l{ra^(~lp|Nq1R(

0PzB z#R0jlNzbCoC`X!|HHH#o$^0(*(nb5%B`)m`ik?3gKrL8?JHm|0D<(=j-`U5isaQLF zDni_+;Se->_C!@NL}vHaDmKL_RwVY>` zK+7w$CDn$Jjy3fOVr?rs>bcXz2cKq6NZey_ZSR7p4Xe6gI5L)aNV`I{vs4kh;E71D#tFUN9&Ahkc6P@D zb3|WmqwcDAoAPa8I)+I|tOK##xKMV7YMJAo`5D^;yd15%H|%SO?SWD$`i>BxZz}T) zMcf>rsU(-lQ`d!~B?FrZ(z6)|LpshXXkl1<6pP{WC}Zc2|62EcLl!?Ml|O8e*9(p= zaa7?|mVPvLN8D`{K|Q%=(jl+4AMWPs*pAW*l``f*j2+c}66=8aP@B5=Nj?#Du*?15u9WbiWi%#6U zSS}gF(`Dk-pl|8j7T>`~`uO#+3_y6=!PXtItqY^5+7rxeAhWEDZoqsNrK8%aD;-j~ zl100s=q0$1n|t+aw{KtLT9tci?sk{g9*$C-ma`tp{=Regy~rBZ^!0`KWo<;!8kenV z`0nm4AkI(uv>%_V;AJ)J2RqoY#nuWc$_-iUan{aoxnX) zZ+;I!WTeZqCB5%$z39lIpc0A^rouX6C0*~4VzMWsg9)lmqw9)e~tU%X8bL!iN2;jfwbOr$jfmbwF08X-&Vc4^@n zt|S zBzwf5;3*S9hs-u{@71$ZO{TSqoXAcq#g2|vD5+?1Q7a~Lq(6irqn}%bujk6&iPWZH zmo%_-b~FZ=(=OGj_wY|rgm)A{Kz;Wg%c1tKeIc57FTE?WsT61I0}E`$2#>h zoBJ;Ee;@SF6wYk#>14SyKn8u4x)CazK6k6#Ffu8P$sToHAm_NVk1`Aes&*7ymuC%3 zTCLN82wQeoL=Y))Gx-7Q$fQLKj0hQGRx<}w_=j5Dl{YU=O|twc-SxiR-6-Gklpcj4 zzi;~4YdeUxLZpQ%jpD+H_uQ?$)~Xd0SdK0OM_2UG3g`)1Rat&6ZCK>@IV=5G(8m<* z>g3`*W|YL>n=((-)27nh^#*E0*LEz}Q@OCVe^%|>@v1!Zt+wEsIlIr~T^jumVhHpl z-y0{5bR;aY$*?CxQwDV)^-b2cbE0@YWxCB#q^iAEC4@D_Xze7MUP=44jjdGDjtjN@nHX4@fhX(3FuEizbNB>%Hh{?_yYgRAPq%%3g{GjXrJ$mfvucR Tx*hmk1iZB=@lEC%2R`^W{Z-t% literal 0 HcmV?d00001 diff --git a/assets/adaptive-icon-dev.png b/assets/adaptive-icon-dev.png new file mode 100644 index 0000000000000000000000000000000000000000..f5bb88a7d4ced517cd0ff65f542c787074134ffc GIT binary patch literal 56739 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 RBw_H!#K2rX?{}AT{|ABL#pVD2 literal 0 HcmV?d00001 diff --git a/assets/adaptive-icon-preview.png b/assets/adaptive-icon-preview.png new file mode 100644 index 0000000000000000000000000000000000000000..c6d0c4ab1f6aaa699d172e738fe3b7977970a4ee GIT binary patch literal 79588 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 literal 0 HcmV?d00001 From 8d439ee39c2b3ed4eb42d9fcb26186a564b6c627 Mon Sep 17 00:00:00 2001 From: Justin Wyne <1986068+wyne@users.noreply.github.com> Date: Sat, 23 Mar 2024 00:54:33 -0700 Subject: [PATCH 008/150] Build 74 --- app.config.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app.config.js b/app.config.js index f52ae147..ac93e091 100644 --- a/app.config.js +++ b/app.config.js @@ -68,7 +68,7 @@ export default { bundleIdentifier: packageName, supportsTablet: true, requireFullScreen: false, - buildNumber: "73", + buildNumber: "74", infoPlist: { RCTAsyncStorageExcludeFromBackup: false, }, @@ -82,7 +82,7 @@ export default { }, package: packageName, permissions: [], - versionCode: 73, + versionCode: 74, googleServicesFile: "./google-services.json", }, userInterfaceStyle: "dark", From be2ab927b046ee1c2f230fcd337524dd908156f5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Mar 2024 09:25:03 +0000 Subject: [PATCH 009/150] Bump @react-navigation/native from 6.1.9 to 6.1.17 Bumps [@react-navigation/native](https://github.com/react-navigation/react-navigation/tree/HEAD/packages/native) from 6.1.9 to 6.1.17. - [Release notes](https://github.com/react-navigation/react-navigation/releases) - [Changelog](https://github.com/react-navigation/react-navigation/blob/@react-navigation/native@6.1.17/packages/native/CHANGELOG.md) - [Commits](https://github.com/react-navigation/react-navigation/commits/@react-navigation/native@6.1.17/packages/native) --- updated-dependencies: - dependency-name: "@react-navigation/native" dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- package-lock.json | 18 +++++++++--------- package.json | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0ebcae55..e9d0e12a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,7 +19,7 @@ "@react-native-menu/menu": "^0.8.0", "@react-native-picker/picker": "2.6.1", "@react-navigation/drawer": "^6.6.2", - "@react-navigation/native": "^6.1.4", + "@react-navigation/native": "^6.1.17", "@react-navigation/native-stack": "^6.9.12", "@reduxjs/toolkit": "^1.9.3", "colorsheet": "^1.0.5", @@ -7741,16 +7741,16 @@ } }, "node_modules/@react-navigation/core": { - "version": "6.4.10", - "resolved": "https://registry.npmjs.org/@react-navigation/core/-/core-6.4.10.tgz", - "integrity": "sha512-oYhqxETRHNHKsipm/BtGL0LI43Hs2VSFoWMbBdHK9OqgQPjTVUitslgLcPpo4zApCcmBWoOLX2qPxhsBda644A==", + "version": "6.4.16", + "resolved": "https://registry.npmjs.org/@react-navigation/core/-/core-6.4.16.tgz", + "integrity": "sha512-UDTJBsHxnzgFETR3ZxhctP+RWr4SkyeZpbhpkQoIGOuwSCkt1SE0qjU48/u6r6w6XlX8OqVudn1Ab0QFXTHxuQ==", "dependencies": { "@react-navigation/routers": "^6.1.9", "escape-string-regexp": "^4.0.0", "nanoid": "^3.1.23", "query-string": "^7.1.3", "react-is": "^16.13.0", - "use-latest-callback": "^0.1.7" + "use-latest-callback": "^0.1.9" }, "peerDependencies": { "react": "*" @@ -7787,11 +7787,11 @@ } }, "node_modules/@react-navigation/native": { - "version": "6.1.9", - "resolved": "https://registry.npmjs.org/@react-navigation/native/-/native-6.1.9.tgz", - "integrity": "sha512-AMuJDpwXE7UlfyhIXaUCCynXmv69Kb8NzKgKJO7v0k0L+u6xUTbt6xvshmJ79vsvaFyaEH9Jg5FMzek5/S5qNw==", + "version": "6.1.17", + "resolved": "https://registry.npmjs.org/@react-navigation/native/-/native-6.1.17.tgz", + "integrity": "sha512-mer3OvfwWOHoUSMJyLa4vnBH3zpFmCwuzrBPlw7feXklurr/ZDiLjLxUScOot6jLRMz/67GyilEYMmP99LL0RQ==", "dependencies": { - "@react-navigation/core": "^6.4.10", + "@react-navigation/core": "^6.4.16", "escape-string-regexp": "^4.0.0", "fast-deep-equal": "^3.1.3", "nanoid": "^3.1.23" diff --git a/package.json b/package.json index b9a2a54e..89fe6622 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "@react-native-menu/menu": "^0.8.0", "@react-native-picker/picker": "2.6.1", "@react-navigation/drawer": "^6.6.2", - "@react-navigation/native": "^6.1.4", + "@react-navigation/native": "^6.1.17", "@react-navigation/native-stack": "^6.9.12", "@reduxjs/toolkit": "^1.9.3", "colorsheet": "^1.0.5", From 33200cba55ceededf1d04b91f05ba72d6d2f9f70 Mon Sep 17 00:00:00 2001 From: Justin Wyne <1986068+wyne@users.noreply.github.com> Date: Tue, 26 Mar 2024 22:06:23 -0700 Subject: [PATCH 010/150] Disable font scaling --- src/components/PlayerTiles/AdditionTile/AdditionTile.tsx | 2 +- src/components/PlayerTiles/AdditionTile/ScoreAfter.tsx | 1 + src/components/PlayerTiles/AdditionTile/ScoreBefore.tsx | 1 + src/components/PlayerTiles/AdditionTile/ScoreRound.tsx | 1 + 4 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/components/PlayerTiles/AdditionTile/AdditionTile.tsx b/src/components/PlayerTiles/AdditionTile/AdditionTile.tsx index ec4e21ef..7881a1fb 100644 --- a/src/components/PlayerTiles/AdditionTile/AdditionTile.tsx +++ b/src/components/PlayerTiles/AdditionTile/AdditionTile.tsx @@ -56,7 +56,7 @@ const AdditionTile: React.FunctionComponent = ({ return ( - + {playerName} diff --git a/src/components/PlayerTiles/AdditionTile/ScoreAfter.tsx b/src/components/PlayerTiles/AdditionTile/ScoreAfter.tsx index 48e86483..69c639b6 100644 --- a/src/components/PlayerTiles/AdditionTile/ScoreAfter.tsx +++ b/src/components/PlayerTiles/AdditionTile/ScoreAfter.tsx @@ -41,6 +41,7 @@ const ScoreAfter: React.FunctionComponent = ({ containerWidth, roundScore return ( {totalScore} diff --git a/src/components/PlayerTiles/AdditionTile/ScoreBefore.tsx b/src/components/PlayerTiles/AdditionTile/ScoreBefore.tsx index e9047031..d73b3f33 100644 --- a/src/components/PlayerTiles/AdditionTile/ScoreBefore.tsx +++ b/src/components/PlayerTiles/AdditionTile/ScoreBefore.tsx @@ -51,6 +51,7 @@ const ScoreBefore: React.FunctionComponent = ({ return ( = ({ containerWidth, roundScore return ( Date: Wed, 27 Mar 2024 01:25:33 -0700 Subject: [PATCH 011/150] Add store review prompt --- redux/SettingsSlice.ts | 8 +++++- redux/selectors.ts | 9 +++++++ redux/store.ts | 1 + src/components/Buttons/HomeButton.tsx | 36 +++++++++++++++++++++++++++ 4 files changed, 53 insertions(+), 1 deletion(-) diff --git a/redux/SettingsSlice.ts b/redux/SettingsSlice.ts index eb9cc287..6ac6318e 100644 --- a/redux/SettingsSlice.ts +++ b/redux/SettingsSlice.ts @@ -13,6 +13,7 @@ export interface SettingsState { onboarded: string | undefined; showPointParticles: boolean; interactionType: InteractionType; + lastStoreReviewPrompt: number; }; const initialState: SettingsState = { @@ -24,6 +25,7 @@ const initialState: SettingsState = { onboarded: undefined, showPointParticles: true, interactionType: InteractionType.SwipeVertical, + lastStoreReviewPrompt: 0, }; const settingsSlice = createSlice({ @@ -55,7 +57,10 @@ const settingsSlice = createSlice({ const appVersion = new SemVer(Application.nativeApplicationVersion || '0.0.0'); console.log(`Setting Onboarded Version: ${appVersion}`); state.onboarded = valid(appVersion) || '0.0.0'; - } + }, + setLastStoreReviewPrompt(state, action: PayloadAction) { + state.lastStoreReviewPrompt = action.payload; + }, } }); @@ -68,6 +73,7 @@ export const { setOnboardedVersion, toggleshowPointParticles, setInteractionType, + setLastStoreReviewPrompt, } = settingsSlice.actions; export default settingsSlice.reducer; diff --git a/redux/selectors.ts b/redux/selectors.ts index 1aef08a3..c017826f 100644 --- a/redux/selectors.ts +++ b/redux/selectors.ts @@ -1,5 +1,6 @@ import { InteractionType } from '../src/components/Interactions/InteractionType'; +import { selectGameById } from './GamesSlice'; import { RootState } from './store'; // Import your RootState type export const selectInteractionType = (state: RootState) => { @@ -13,3 +14,11 @@ export const selectInteractionType = (state: RootState) => { return safeInteractionType; }; + +export const selectCurrentGame = (state: RootState) => { + const currentGameId = state.settings.currentGameId; + if (!currentGameId) return; + + return selectGameById(state, currentGameId); +}; +export const selectLastStoreReviewPrompt = (state: RootState) => state.settings.lastStoreReviewPrompt; diff --git a/redux/store.ts b/redux/store.ts index b3aadeea..24b8248f 100644 --- a/redux/store.ts +++ b/redux/store.ts @@ -19,6 +19,7 @@ const settingsPersistConfig = { 'onboarded', 'showPointParticles', 'interactionType', + 'lastStoreReviewPrompt', ], }; diff --git a/src/components/Buttons/HomeButton.tsx b/src/components/Buttons/HomeButton.tsx index 1c95e0a8..472ac205 100644 --- a/src/components/Buttons/HomeButton.tsx +++ b/src/components/Buttons/HomeButton.tsx @@ -3,8 +3,13 @@ import React from 'react'; import analytics from '@react-native-firebase/analytics'; import { ParamListBase } from '@react-navigation/native'; import { NativeStackNavigationProp } from '@react-navigation/native-stack'; +import * as StoreReview from 'expo-store-review'; +import { Platform } from 'react-native'; import { Icon } from 'react-native-elements/dist/icons/Icon'; +import { useAppDispatch, useAppSelector } from '../../../redux/hooks'; +import { selectCurrentGame, selectLastStoreReviewPrompt } from '../../../redux/selectors'; +import { setLastStoreReviewPrompt } from '../../../redux/SettingsSlice'; import { systemBlue } from '../../constants'; import HeaderButton from './HeaderButton'; @@ -14,10 +19,41 @@ interface Props { } const HomeButton: React.FunctionComponent = ({ navigation }) => { + const gameCount = useAppSelector((state) => state.games.ids.length); + const currentGame = useAppSelector(selectCurrentGame); + const roundCurrent = currentGame?.roundCurrent || 0; + const lastStoreReviewPrompt = useAppSelector(selectLastStoreReviewPrompt); + const dispatch = useAppDispatch(); + + const storePrompt = async () => { + const now = Date.now(); + const daysSinceLastPrompt = (now - lastStoreReviewPrompt) / (1000 * 60 * 60 * 24); + + if (gameCount < 3) { return; } + if (roundCurrent < 1) { return; } + if (daysSinceLastPrompt < 180) { return; } + + console.log("Prompt for review"); + + dispatch(setLastStoreReviewPrompt(Date.now())); + + const isAvailable = await StoreReview.isAvailableAsync(); + if (isAvailable) { + const platform = Platform.OS; + if (platform === 'ios') { + StoreReview.requestReview(); + } else if (platform === 'android') { + StoreReview.requestReview(); + } + } + }; + return ( { navigation.navigate("List"); await analytics().logEvent('menu'); + + storePrompt(); }}> Date: Wed, 27 Mar 2024 01:44:49 -0700 Subject: [PATCH 012/150] Better redux store typing --- redux/GamesSlice.ts | 21 +++++++++++-------- redux/store.ts | 7 ++++++- src/components/Boards/FlexboxBoard.tsx | 4 ++-- src/components/Boards/FlexboxTile.tsx | 6 ++---- src/components/EditGame.tsx | 7 ++++--- src/components/EditPlayer.tsx | 10 ++++----- .../Interactions/HalfTap/HalfTap.tsx | 6 ++---- .../HalfTap/HalfTileTouchSurface.tsx | 4 ++-- src/components/Interactions/Swipe/Swipe.tsx | 4 ++-- .../PlayerTiles/AdditionTile/AdditionTile.tsx | 5 ++--- src/components/ScoreLog/PlayerNameColumn.tsx | 10 +++++---- src/components/ScoreLog/RoundScoreColumn.tsx | 9 ++++---- src/components/ScoreLog/TotalScoreColumn.tsx | 7 +++---- src/components/Sheets/GameSheet.tsx | 7 ++++--- src/screens/GameScreen.tsx | 4 ++-- src/screens/SettingsScreen.tsx | 5 +++-- src/screens/ShareScreen.tsx | 5 +++-- 17 files changed, 65 insertions(+), 56 deletions(-) diff --git a/redux/GamesSlice.ts b/redux/GamesSlice.ts index 9d949cc2..96d490ec 100644 --- a/redux/GamesSlice.ts +++ b/redux/GamesSlice.ts @@ -2,7 +2,7 @@ import analytics from '@react-native-firebase/analytics'; import { createSlice, PayloadAction, createEntityAdapter, createAsyncThunk, createSelector } from '@reduxjs/toolkit'; import * as Crypto from 'expo-crypto'; -import { playerAdd, selectAllPlayers } from './PlayersSlice'; +import { ScoreState, playerAdd, selectAllPlayers } from './PlayersSlice'; import { setCurrentGameId } from './SettingsSlice'; import { RootState } from './store'; @@ -65,7 +65,7 @@ interface GamesSlice { export const asyncCreateGame = createAsyncThunk( 'games/create', async ( - { gameCount, playerCount }: { gameCount: number, playerCount: number }, + { gameCount, playerCount }: { gameCount: number, playerCount: number; }, { dispatch } ) => { const newGameId = Crypto.randomUUID(); @@ -105,14 +105,17 @@ export const asyncCreateGame = createAsyncThunk( export const selectSortedPlayers = createSelector( [ selectAllPlayers, - (state: RootState) => state.games.entities[state.settings.currentGameId] + (state: RootState) => state.settings.currentGameId ? state.games.entities[state.settings.currentGameId] : undefined ], - (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); - }) + (players: ScoreState[], currentGame: GameState | undefined) => { + if (!currentGame) return []; + + return 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 { diff --git a/redux/store.ts b/redux/store.ts index 24b8248f..504acbf7 100644 --- a/redux/store.ts +++ b/redux/store.ts @@ -52,7 +52,12 @@ export const store = configureStore({ }); // Infer the `RootState` and `AppDispatch` types from the store itself -export type RootState = ReturnType; +export interface RootState { + settings: ReturnType; + games: ReturnType; + players: ReturnType; +} + // Inferred type: {posts: PostsState, comments: CommentsState, users: UsersState} export type AppDispatch = typeof store.dispatch; diff --git a/src/components/Boards/FlexboxBoard.tsx b/src/components/Boards/FlexboxBoard.tsx index 56136e0d..5ffe3c1a 100644 --- a/src/components/Boards/FlexboxBoard.tsx +++ b/src/components/Boards/FlexboxBoard.tsx @@ -4,8 +4,8 @@ import { getContrastRatio } from 'colorsheet'; import { LayoutChangeEvent, StyleSheet } from 'react-native'; import { SafeAreaView } from 'react-native-safe-area-context'; -import { selectGameById } from '../../../redux/GamesSlice'; import { useAppSelector } from '../../../redux/hooks'; +import { selectCurrentGame } from '../../../redux/selectors'; import { bottomSheetHeight } from '../../components/Sheets/GameSheet'; import FlexboxTile from './FlexboxTile'; @@ -22,7 +22,7 @@ const FlexboxBoard: React.FC = () => { const [rows, setRows] = useState(0); const [cols, setCols] = useState(0); const fullscreen = useAppSelector(state => state.settings.home_fullscreen); - const currentGame = useAppSelector(state => selectGameById(state, state.settings.currentGameId)); + const currentGame = useAppSelector(selectCurrentGame); const [width, setWidth] = useState(null); const [height, setHeight] = useState(null); diff --git a/src/components/Boards/FlexboxTile.tsx b/src/components/Boards/FlexboxTile.tsx index 3b8df2bd..7158802b 100644 --- a/src/components/Boards/FlexboxTile.tsx +++ b/src/components/Boards/FlexboxTile.tsx @@ -3,9 +3,8 @@ import React from 'react'; import { DimensionValue, StyleSheet } from 'react-native'; import Animated, { Easing, FadeIn } from 'react-native-reanimated'; -import { selectGameById } from '../../../redux/GamesSlice'; import { useAppSelector } from '../../../redux/hooks'; -import { selectInteractionType } from '../../../redux/selectors'; +import { selectCurrentGame, selectInteractionType } from '../../../redux/selectors'; import { interactionComponents } from '../Interactions/InteractionComponents'; import { InteractionType } from '../Interactions/InteractionType'; import AdditionTile from '../PlayerTiles/AdditionTile/AdditionTile'; @@ -35,8 +34,7 @@ const FlexboxTile: React.FunctionComponent = ({ if (!(width > 0 && height > 0)) return null; if (Number.isNaN(width) || Number.isNaN(height)) return null; - const currentGameId = useAppSelector(state => state.settings.currentGameId); - const currentGame = useAppSelector(state => selectGameById(state, currentGameId)); + const currentGame = useAppSelector(selectCurrentGame); if (typeof currentGame == 'undefined') return null; const widthPerc: DimensionValue = `${(100 / cols)}%`; diff --git a/src/components/EditGame.tsx b/src/components/EditGame.tsx index c51f28d8..f4271656 100644 --- a/src/components/EditGame.tsx +++ b/src/components/EditGame.tsx @@ -1,16 +1,17 @@ import React, { useState } from 'react'; -import { Text, View, StyleSheet, NativeSyntheticEvent, TextInputEndEditingEventData } from 'react-native'; +import { NativeSyntheticEvent, StyleSheet, Text, TextInputEndEditingEventData, View } from 'react-native'; import { Input } from 'react-native-elements'; -import { selectGameById, updateGame } from '../../redux/GamesSlice'; +import { updateGame } from '../../redux/GamesSlice'; import { useAppDispatch, useAppSelector } from '../../redux/hooks'; +import { selectCurrentGame } from '../../redux/selectors'; const UNTITLED = "Untitled"; const EditGame = ({ }) => { const dispatch = useAppDispatch(); - const currentGame = useAppSelector(state => selectGameById(state, state.settings.currentGameId)); + const currentGame = useAppSelector(selectCurrentGame); if (typeof currentGame == 'undefined') return null; diff --git a/src/components/EditPlayer.tsx b/src/components/EditPlayer.tsx index 258ad0a4..0b93b796 100644 --- a/src/components/EditPlayer.tsx +++ b/src/components/EditPlayer.tsx @@ -1,16 +1,16 @@ import React from 'react'; import analytics from '@react-native-firebase/analytics'; -import { Text, View, StyleSheet, TouchableOpacity, NativeSyntheticEvent, TextInputEndEditingEventData, Alert } from 'react-native'; +import { Alert, NativeSyntheticEvent, StyleSheet, Text, TextInputEndEditingEventData, TouchableOpacity, View } from 'react-native'; import { Icon, Input } from 'react-native-elements'; import Animated from 'react-native-reanimated'; -import { selectGameById, updateGame } from '../../redux/GamesSlice'; +import { updateGame } from '../../redux/GamesSlice'; import { useAppDispatch, useAppSelector } from '../../redux/hooks'; -import { selectPlayerById , removePlayer, updatePlayer } from '../../redux/PlayersSlice'; +import { removePlayer, selectPlayerById, updatePlayer } from '../../redux/PlayersSlice'; +import { selectCurrentGame } from '../../redux/selectors'; import { palette } from '../constants'; - interface Props { playerId: string; index: number; @@ -20,7 +20,7 @@ interface Props { const EditPlayer: React.FunctionComponent = ({ playerId, index, setPlayerWasAdded, playerWasAdded }) => { const dispatch = useAppDispatch(); - const currentGame = useAppSelector(state => selectGameById(state, state.settings.currentGameId)); + const currentGame = useAppSelector(selectCurrentGame); const player = useAppSelector(state => selectPlayerById(state, playerId)); if (typeof currentGame == 'undefined') return null; diff --git a/src/components/Interactions/HalfTap/HalfTap.tsx b/src/components/Interactions/HalfTap/HalfTap.tsx index 90025917..d343d79f 100644 --- a/src/components/Interactions/HalfTap/HalfTap.tsx +++ b/src/components/Interactions/HalfTap/HalfTap.tsx @@ -1,9 +1,8 @@ import React from 'react'; - -import { selectGameById } from '../../../../redux/GamesSlice'; import { useAppSelector } from '../../../../redux/hooks'; import { selectPlayerById } from '../../../../redux/PlayersSlice'; +import { selectCurrentGame } from '../../../../redux/selectors'; import { HalfTileTouchSurface } from './HalfTileTouchSurface'; @@ -20,8 +19,7 @@ const HalfTap: React.FC = ({ fontColor, playerId }) => { - const currentGameId = useAppSelector(state => state.settings.currentGameId); - const currentGame = useAppSelector(state => selectGameById(state, currentGameId)); + const currentGame = useAppSelector(selectCurrentGame); if (typeof currentGame == 'undefined') return null; const player = useAppSelector(state => selectPlayerById(state, playerId)); diff --git a/src/components/Interactions/HalfTap/HalfTileTouchSurface.tsx b/src/components/Interactions/HalfTap/HalfTileTouchSurface.tsx index 6c95a676..9a232a77 100644 --- a/src/components/Interactions/HalfTap/HalfTileTouchSurface.tsx +++ b/src/components/Interactions/HalfTap/HalfTileTouchSurface.tsx @@ -4,9 +4,9 @@ import analytics from '@react-native-firebase/analytics'; import * as Haptics from 'expo-haptics'; import { StyleSheet, TouchableHighlight, View } from 'react-native'; -import { selectGameById } from '../../../../redux/GamesSlice'; import { useAppDispatch, useAppSelector } from '../../../../redux/hooks'; import { playerRoundScoreIncrement } from '../../../../redux/PlayersSlice'; +import { selectCurrentGame } from '../../../../redux/selectors'; import { ScoreParticle } from '../../PlayerTiles/AdditionTile/ScoreParticle'; type ScoreParticleProps = { @@ -33,7 +33,7 @@ export const HalfTileTouchSurface: React.FunctionComponent = ( const addendTwo = useAppSelector(state => state.settings.addendTwo); const currentGameId = useAppSelector(state => state.settings.currentGameId); - const currentGame = useAppSelector(state => selectGameById(state, currentGameId)); + const currentGame = useAppSelector(selectCurrentGame); if (typeof currentGame == 'undefined') return null; const roundCurrent = currentGame.roundCurrent; diff --git a/src/components/Interactions/Swipe/Swipe.tsx b/src/components/Interactions/Swipe/Swipe.tsx index d8198cef..329406e7 100644 --- a/src/components/Interactions/Swipe/Swipe.tsx +++ b/src/components/Interactions/Swipe/Swipe.tsx @@ -6,9 +6,9 @@ import { Animated, StyleSheet, View } from 'react-native'; import { PanGestureHandler, PanGestureHandlerStateChangeEvent, State } from 'react-native-gesture-handler'; import { runOnJS, useAnimatedReaction, useSharedValue } from 'react-native-reanimated'; -import { selectGameById } from '../../../../redux/GamesSlice'; import { useAppDispatch, useAppSelector } from '../../../../redux/hooks'; import { playerRoundScoreIncrement } from '../../../../redux/PlayersSlice'; +import { selectCurrentGame } from '../../../../redux/selectors'; interface HalfTapProps { children: React.ReactNode; @@ -27,7 +27,7 @@ const SwipeVertical: React.FC = ({ //#region Selector setup const currentGameId = useAppSelector(state => state.settings.currentGameId); - const currentGame = useAppSelector(state => selectGameById(state, currentGameId)); + const currentGame = useAppSelector(selectCurrentGame); if (typeof currentGame == 'undefined') return null; const roundCurrent = currentGame.roundCurrent; diff --git a/src/components/PlayerTiles/AdditionTile/AdditionTile.tsx b/src/components/PlayerTiles/AdditionTile/AdditionTile.tsx index 7881a1fb..7195abdd 100644 --- a/src/components/PlayerTiles/AdditionTile/AdditionTile.tsx +++ b/src/components/PlayerTiles/AdditionTile/AdditionTile.tsx @@ -3,9 +3,9 @@ import React from 'react'; import { StyleSheet } from 'react-native'; import Animated from 'react-native-reanimated'; -import { selectGameById } from '../../../../redux/GamesSlice'; import { useAppSelector } from '../../../../redux/hooks'; import { selectPlayerById } from '../../../../redux/PlayersSlice'; +import { selectCurrentGame } from '../../../../redux/selectors'; import { calculateFontSize } from './Helpers'; import ScoreAfter from './ScoreAfter'; @@ -26,8 +26,7 @@ const AdditionTile: React.FunctionComponent = ({ maxHeight, playerId, }) => { - const currentGameId = useAppSelector(state => state.settings.currentGameId); - const currentGame = useAppSelector(state => selectGameById(state, currentGameId)); + const currentGame = useAppSelector(selectCurrentGame); if (typeof currentGame == 'undefined') return null; const roundCurrent = currentGame.roundCurrent; diff --git a/src/components/ScoreLog/PlayerNameColumn.tsx b/src/components/ScoreLog/PlayerNameColumn.tsx index af125472..011ea6a7 100644 --- a/src/components/ScoreLog/PlayerNameColumn.tsx +++ b/src/components/ScoreLog/PlayerNameColumn.tsx @@ -1,20 +1,22 @@ import React from 'react'; -import { Text, View, StyleSheet } from 'react-native'; +import { StyleSheet, Text, View } from 'react-native'; import { Icon } from 'react-native-elements/dist/icons/Icon'; -import { selectGameById, selectSortedPlayers } from '../../../redux/GamesSlice'; +import { selectSortedPlayers } from '../../../redux/GamesSlice'; import { useAppSelector } from '../../../redux/hooks'; +import { selectCurrentGame } from '../../../redux/selectors'; import { palette, systemBlue } from '../../constants'; const PlayerNameColumn: React.FunctionComponent = ({ }) => { - const currentGameId = useAppSelector(state => state.settings.currentGameId); - const currentGame = useAppSelector(state => selectGameById(state, currentGameId)); + const currentGame = useAppSelector(selectCurrentGame); if (currentGame == undefined) return null; const players = useAppSelector(selectSortedPlayers); + if (players == undefined) return null; + return ( diff --git a/src/components/ScoreLog/RoundScoreColumn.tsx b/src/components/ScoreLog/RoundScoreColumn.tsx index b86feed0..b0ed0068 100644 --- a/src/components/ScoreLog/RoundScoreColumn.tsx +++ b/src/components/ScoreLog/RoundScoreColumn.tsx @@ -1,10 +1,11 @@ import React, { memo, useCallback } from 'react'; import analytics from '@react-native-firebase/analytics'; -import { Text, View , TouchableWithoutFeedback } from 'react-native'; +import { Text, TouchableWithoutFeedback, View } from 'react-native'; -import { selectGameById, updateGame } from '../../../redux/GamesSlice'; +import { updateGame } from '../../../redux/GamesSlice'; import { useAppDispatch, useAppSelector } from '../../../redux/hooks'; +import { selectCurrentGame } from '../../../redux/selectors'; import RoundScoreCell from './RoundScoreCell'; @@ -18,12 +19,12 @@ const RoundScoreColumn: React.FunctionComponent = ({ round, isCurrentRoun const dispatch = useAppDispatch(); const currentGameId = useAppSelector(state => state.settings.currentGameId); - const currentGame = useAppSelector(state => selectGameById(state, currentGameId)); + const currentGame = useAppSelector(selectCurrentGame); if (typeof currentGame == 'undefined') return null; const onPressHandler = useCallback(async () => { - if (disabled) return; + if (disabled || !currentGameId) return; dispatch(updateGame({ id: currentGameId, diff --git a/src/components/ScoreLog/TotalScoreColumn.tsx b/src/components/ScoreLog/TotalScoreColumn.tsx index 8c8f5f6b..c0a6b49c 100644 --- a/src/components/ScoreLog/TotalScoreColumn.tsx +++ b/src/components/ScoreLog/TotalScoreColumn.tsx @@ -1,15 +1,14 @@ import React from 'react'; -import { Text, View, StyleSheet } from 'react-native'; +import { StyleSheet, Text, View } from 'react-native'; -import { selectGameById } from '../../../redux/GamesSlice'; import { useAppSelector } from '../../../redux/hooks'; +import { selectCurrentGame } from '../../../redux/selectors'; import TotalScoreCell from './TotalScoreCell'; const TotalScoreColumn = ({ }) => { - const currentGameId = useAppSelector(state => state.settings.currentGameId); - const currentGame = useAppSelector(state => selectGameById(state, currentGameId)); + const currentGame = useAppSelector(selectCurrentGame); if (typeof currentGame == 'undefined') return null; diff --git a/src/components/Sheets/GameSheet.tsx b/src/components/Sheets/GameSheet.tsx index 1e0a2377..53037447 100644 --- a/src/components/Sheets/GameSheet.tsx +++ b/src/components/Sheets/GameSheet.tsx @@ -3,14 +3,15 @@ import React, { useCallback, useMemo, useState } from 'react'; import BottomSheet, { BottomSheetBackdrop, BottomSheetBackdropProps, BottomSheetScrollView } from '@gorhom/bottom-sheet'; import { ParamListBase, useIsFocused } from '@react-navigation/native'; import { NativeStackNavigationProp } from '@react-navigation/native-stack'; -import { View, StyleSheet, Text, Alert, TouchableWithoutFeedback, Platform } from 'react-native'; +import { Alert, Platform, StyleSheet, Text, TouchableWithoutFeedback, View } 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, selectSortedPlayers, updateGame } from '../../../redux/GamesSlice'; +import { selectSortedPlayers, updateGame } from '../../../redux/GamesSlice'; import { useAppDispatch, useAppSelector } from '../../../redux/hooks'; import { updatePlayer } from '../../../redux/PlayersSlice'; +import { selectCurrentGame } from '../../../redux/selectors'; import { systemBlue } from '../../constants'; import BigButton from '../BigButtons/BigButton'; import Rounds from '../Rounds'; @@ -34,7 +35,7 @@ const GameSheet: React.FunctionComponent = ({ navigation, containerHeight if (typeof currentGameId == 'undefined') return null; const fullscreen = useAppSelector(state => state.settings.home_fullscreen); - const currentGame = useAppSelector(state => selectGameById(state, state.settings.currentGameId)); + const currentGame = useAppSelector(selectCurrentGame); if (currentGame == undefined) return null; diff --git a/src/screens/GameScreen.tsx b/src/screens/GameScreen.tsx index 0af7bc7d..0c846ab7 100644 --- a/src/screens/GameScreen.tsx +++ b/src/screens/GameScreen.tsx @@ -4,8 +4,8 @@ import { ParamListBase } from '@react-navigation/native'; import { NativeStackNavigationProp } from '@react-navigation/native-stack'; import { LayoutChangeEvent, StyleSheet, View } from 'react-native'; -import { selectGameById } from '../../redux/GamesSlice'; import { useAppSelector } from '../../redux/hooks'; +import { selectCurrentGame } from '../../redux/selectors'; import FlexboxBoard from '../components/Boards/FlexboxBoard'; import AddendModal from '../components/Sheets/AddendModal'; import GameSheet from '../components/Sheets/GameSheet'; @@ -19,7 +19,7 @@ const ScoreBoardScreen: React.FunctionComponent = ({ navigation }) => { if (typeof currentGameId == 'undefined') return null; const fullscreen = useAppSelector(state => state.settings.home_fullscreen); - const currentGame = useAppSelector(state => selectGameById(state, state.settings.currentGameId)); + const currentGame = useAppSelector(selectCurrentGame); if (currentGame == undefined) return null; diff --git a/src/screens/SettingsScreen.tsx b/src/screens/SettingsScreen.tsx index 06f3ca35..00b384b3 100644 --- a/src/screens/SettingsScreen.tsx +++ b/src/screens/SettingsScreen.tsx @@ -9,9 +9,10 @@ import { Button, Icon } from 'react-native-elements'; import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view'; import Animated, { Layout } from 'react-native-reanimated'; -import { selectGameById, selectSortedPlayers, updateGame, } from '../../redux/GamesSlice'; +import { selectSortedPlayers, updateGame } from '../../redux/GamesSlice'; import { useAppDispatch, useAppSelector } from '../../redux/hooks'; import { playerAdd } from '../../redux/PlayersSlice'; +import { selectCurrentGame } from '../../redux/selectors'; import EditGame from '../components/EditGame'; import EditPlayer from '../components/EditPlayer'; import { systemBlue } from '../constants'; @@ -34,7 +35,7 @@ const SettingsScreen: React.FunctionComponent = ({ }) => { const currentGameId = useAppSelector(state => state.settings.currentGameId); if (typeof currentGameId == 'undefined') return null; - const currentGame = useAppSelector(state => selectGameById(state, state.settings.currentGameId)); + const currentGame = useAppSelector(selectCurrentGame); const players = useAppSelector(selectSortedPlayers); const maxPlayers = 12; diff --git a/src/screens/ShareScreen.tsx b/src/screens/ShareScreen.tsx index 01aafeef..9944a0e1 100644 --- a/src/screens/ShareScreen.tsx +++ b/src/screens/ShareScreen.tsx @@ -4,13 +4,14 @@ import analytics from '@react-native-firebase/analytics'; import { ParamListBase } from '@react-navigation/native'; import { NativeStackNavigationProp } from '@react-navigation/native-stack'; import * as Sharing from 'expo-sharing'; -import { View, StyleSheet, ScrollView, Text } from 'react-native'; +import { ScrollView, StyleSheet, Text, View } from 'react-native'; import { Button, Icon } from 'react-native-elements'; import { SafeAreaView } from 'react-native-safe-area-context'; import { captureRef } from "react-native-view-shot"; import { selectGameById } from '../../redux/GamesSlice'; import { useAppSelector } from '../../redux/hooks'; +import { selectCurrentGame } from '../../redux/selectors'; import PlayerNameColumn from '../components/ScoreLog/PlayerNameColumn'; import RoundScoreColumn from '../components/ScoreLog/RoundScoreColumn'; import TotalScoreColumn from '../components/ScoreLog/TotalScoreColumn'; @@ -25,7 +26,7 @@ const ShareScreen: React.FunctionComponent = ({ navigation }) => { if (typeof currentGameId == 'undefined') return null; const roundTotal = useAppSelector(state => selectGameById(state, currentGameId)?.roundTotal || 0); - const currentGame = useAppSelector(state => selectGameById(state, state.settings.currentGameId)); + const currentGame = useAppSelector(selectCurrentGame); if (typeof currentGame == 'undefined') return null; const roundsScrollViewEl = useRef(null); From 0e056684a674a375434fd1ca8a7718c400e85618 Mon Sep 17 00:00:00 2001 From: Justin Wyne <1986068+wyne@users.noreply.github.com> Date: Wed, 27 Mar 2024 01:46:49 -0700 Subject: [PATCH 013/150] Analytics --- src/components/Buttons/HomeButton.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Buttons/HomeButton.tsx b/src/components/Buttons/HomeButton.tsx index 472ac205..4bf73483 100644 --- a/src/components/Buttons/HomeButton.tsx +++ b/src/components/Buttons/HomeButton.tsx @@ -33,7 +33,7 @@ const HomeButton: React.FunctionComponent = ({ navigation }) => { if (roundCurrent < 1) { return; } if (daysSinceLastPrompt < 180) { return; } - console.log("Prompt for review"); + await analytics().logEvent('review_prompt'); dispatch(setLastStoreReviewPrompt(Date.now())); From 5d0840abbffd7794a37f1dd22b852e5c4d48d876 Mon Sep 17 00:00:00 2001 From: Justin Wyne <1986068+wyne@users.noreply.github.com> Date: Wed, 27 Mar 2024 01:59:39 -0700 Subject: [PATCH 014/150] v2.5.1 build 75 --- app.config.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app.config.js b/app.config.js index ac93e091..a02759f1 100644 --- a/app.config.js +++ b/app.config.js @@ -59,7 +59,7 @@ switch (variant) { export default { name: name, slug: "scorepad", - version: "2.5.0", + version: "2.5.1", orientation: "default", icon: icon, assetBundlePatterns: ["assets/*"], @@ -68,7 +68,7 @@ export default { bundleIdentifier: packageName, supportsTablet: true, requireFullScreen: false, - buildNumber: "74", + buildNumber: "75", infoPlist: { RCTAsyncStorageExcludeFromBackup: false, }, @@ -82,7 +82,7 @@ export default { }, package: packageName, permissions: [], - versionCode: 74, + versionCode: 75, googleServicesFile: "./google-services.json", }, userInterfaceStyle: "dark", From a375a4c1f2be80defc52520ff05abb724ddc4576 Mon Sep 17 00:00:00 2001 From: Justin Wyne <1986068+wyne@users.noreply.github.com> Date: Wed, 27 Mar 2024 17:17:00 -0700 Subject: [PATCH 015/150] Expo doctor dependencies --- .nvmrc | 2 +- eas.json | 4 + package-lock.json | 344 +++++++--------------------------------------- package.json | 10 +- 4 files changed, 58 insertions(+), 302 deletions(-) diff --git a/.nvmrc b/.nvmrc index 67a228a4..4a58985b 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -18.18.0 \ No newline at end of file +18.18 diff --git a/eas.json b/eas.json index bcb9d342..94d02282 100644 --- a/eas.json +++ b/eas.json @@ -5,6 +5,7 @@ }, "build": { "development-simulator": { + "node": "18.18.2", "developmentClient": true, "distribution": "internal", "ios": { @@ -16,6 +17,7 @@ } }, "development": { + "node": "18.18.2", "developmentClient": true, "distribution": "internal", "ios": { @@ -27,6 +29,7 @@ } }, "preview": { + "node": "18.18.2", "distribution": "internal", "ios": { "resourceClass": "m-medium" @@ -38,6 +41,7 @@ } }, "production": { + "node": "18.18.2", "ios": { "resourceClass": "m-medium" }, diff --git a/package-lock.json b/package-lock.json index be7f9841..01fedfe5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,23 +24,23 @@ "@reduxjs/toolkit": "^1.9.3", "colorsheet": "^1.0.5", "dotenv": "^16.0.3", - "expo": "^50.0.13", + "expo": "~50.0.14", "expo-application": "~5.8.3", "expo-blur": "~12.9.2", "expo-build-properties": "~0.11.1", "expo-constants": "~15.4.5", "expo-crypto": "~12.8.1", - "expo-dev-client": "~3.3.10", + "expo-dev-client": "~3.3.11", "expo-device": "~5.9.3", "expo-haptics": "~12.8.1", "expo-image": "~1.10.6", - "expo-linking": "~5.0.2", + "expo-linking": "~6.2.2", "expo-screen-orientation": "~6.4.1", "expo-sensors": "~12.9.1", "expo-sharing": "~11.10.0", "expo-splash-screen": "~0.26.4", "expo-status-bar": "~1.11.1", - "expo-store-review": "~6.4.0", + "expo-store-review": "~6.8.3", "expo-system-ui": "~2.9.3", "expo-updates": "~0.24.12", "firebase": "^9.17.1", @@ -49,7 +49,7 @@ "react": "18.2.0", "react-dom": "18.2.0", "react-moment": "^1.1.3", - "react-native": "0.73.5", + "react-native": "0.73.6", "react-native-animated-pagination-dots": "^0.1.73", "react-native-elements": "^3.4.2", "react-native-gesture-handler": "~2.14.0", @@ -8304,11 +8304,6 @@ "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.11.tgz", "integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==" }, - "node_modules/@types/qs": { - "version": "6.9.11", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.11.tgz", - "integrity": "sha512-oGk0gmhnEJK4Yyk+oI7EfXsLayXatCWPHary1MtcmbAifkobT9cM9yutG/hZKIseOU0MqbIwQ/u2nn/Gb+ltuQ==" - }, "node_modules/@types/react": { "version": "18.2.45", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.45.tgz", @@ -9659,6 +9654,7 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dev": true, "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", @@ -10719,6 +10715,7 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", @@ -11149,6 +11146,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dev": true, "dependencies": { "get-intrinsic": "^1.2.4" }, @@ -11160,6 +11158,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, "engines": { "node": ">= 0.4" } @@ -12004,9 +12003,9 @@ } }, "node_modules/expo": { - "version": "50.0.13", - "resolved": "https://registry.npmjs.org/expo/-/expo-50.0.13.tgz", - "integrity": "sha512-p0FYrhUJZe92YOwOXx6GZ/WaxF6YtsLXtWkql9pFIIocYBN6iQ3OMGsbQCRSu0ao8rlxsk7HgQDEWK4D+y9tAg==", + "version": "50.0.14", + "resolved": "https://registry.npmjs.org/expo/-/expo-50.0.14.tgz", + "integrity": "sha512-yLPdxCMVAbmeEIpzzyAuJ79wvr6ToDDtQmuLDMAgWtjqP8x3CGddXxUe07PpKEQgzwJabdHvCLP5Bv94wMFIjQ==", "dependencies": { "@babel/runtime": "^7.20.0", "@expo/cli": "0.17.8", @@ -12112,12 +12111,12 @@ } }, "node_modules/expo-dev-client": { - "version": "3.3.10", - "resolved": "https://registry.npmjs.org/expo-dev-client/-/expo-dev-client-3.3.10.tgz", - "integrity": "sha512-UhZOJ+O90dRo7S/rmFmVIWwa/HxOqoQ4ySCqvWh87O3pFQuluPfVI9PdKicF4djYrNHZZmE8UXqBDN41hiYtAA==", + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/expo-dev-client/-/expo-dev-client-3.3.11.tgz", + "integrity": "sha512-9nhhbfbskfmjp/tlRS5KvDpCoW0BREJBxpu2GyjKu7nDB33W8fJLL0wXgNhP+QEb93r37o3uezKmUm2kibOvTw==", "dependencies": { - "expo-dev-launcher": "3.6.8", - "expo-dev-menu": "4.5.7", + "expo-dev-launcher": "3.6.9", + "expo-dev-menu": "4.5.8", "expo-dev-menu-interface": "1.7.2", "expo-manifests": "~0.13.0", "expo-updates-interface": "~0.15.1" @@ -12127,12 +12126,12 @@ } }, "node_modules/expo-dev-launcher": { - "version": "3.6.8", - "resolved": "https://registry.npmjs.org/expo-dev-launcher/-/expo-dev-launcher-3.6.8.tgz", - "integrity": "sha512-lFyxRXpUk0z7V7BDd1tFg/M9eFPzo+WRq7kQBA4F8bFPX6drYuTjPqs/bEF/6A5S38oA1wcA34bY9TNgkiKf5w==", + "version": "3.6.9", + "resolved": "https://registry.npmjs.org/expo-dev-launcher/-/expo-dev-launcher-3.6.9.tgz", + "integrity": "sha512-MBDMAqjCMVYt1Zv47u2dJTp4d8gCZMfM4GWAFhfQy3G6XzkUlFtewaQefAqy93FcYOv6BYdC9yZOLOb06tqTfA==", "dependencies": { "ajv": "8.11.0", - "expo-dev-menu": "4.5.7", + "expo-dev-menu": "4.5.8", "expo-manifests": "~0.13.0", "resolve-from": "^5.0.0", "semver": "^7.5.3" @@ -12162,9 +12161,9 @@ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" }, "node_modules/expo-dev-menu": { - "version": "4.5.7", - "resolved": "https://registry.npmjs.org/expo-dev-menu/-/expo-dev-menu-4.5.7.tgz", - "integrity": "sha512-yIAsiKIhxvAmzd6x25HTvANeengGg2Uax6JnKy7+YfxgynKtqmWUlGCyc9EECoQI4+ItxbfjU4fSTxTiQYGFug==", + "version": "4.5.8", + "resolved": "https://registry.npmjs.org/expo-dev-menu/-/expo-dev-menu-4.5.8.tgz", + "integrity": "sha512-GXfI0CmYlqjOqyFjtplXO9PSoJQoy89+50lbUSNZykDsGyvzCPzl4txdQcdHHSglKYr7lWV7aeMVeehuSct60w==", "dependencies": { "expo-dev-menu-interface": "1.7.2", "semver": "^7.5.3" @@ -12249,249 +12248,14 @@ } }, "node_modules/expo-linking": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/expo-linking/-/expo-linking-5.0.2.tgz", - "integrity": "sha512-SPQus0+tYGx9c69Uw4wmdo3rkKX8vRT1vyJz/mvkpSlZN986s0NmP/V0M5vDv5Zv2qZzVdqJyuITFe0Pg5aI+A==", - "dependencies": { - "@types/qs": "^6.9.7", - "expo-constants": "~14.4.2", - "invariant": "^2.2.4", - "qs": "^6.11.0", - "url-parse": "^1.5.9" - } - }, - "node_modules/expo-linking/node_modules/@babel/code-frame": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", - "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", - "dependencies": { - "@babel/highlight": "^7.10.4" - } - }, - "node_modules/expo-linking/node_modules/@expo/config": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/@expo/config/-/config-8.1.2.tgz", - "integrity": "sha512-4e7hzPj50mQIlsrzOH6XZ36O094mPfPTIDIH4yv49bWNMc7GFLTofB/lcT+QyxiLaJuC0Wlk9yOLB8DIqmtwug==", - "dependencies": { - "@babel/code-frame": "~7.10.4", - "@expo/config-plugins": "~7.2.0", - "@expo/config-types": "^49.0.0-alpha.1", - "@expo/json-file": "^8.2.37", - "getenv": "^1.0.0", - "glob": "7.1.6", - "require-from-string": "^2.0.2", - "resolve-from": "^5.0.0", - "semver": "7.5.3", - "slugify": "^1.3.4", - "sucrase": "^3.20.0" - } - }, - "node_modules/expo-linking/node_modules/@expo/config-plugins": { - "version": "7.2.5", - "resolved": "https://registry.npmjs.org/@expo/config-plugins/-/config-plugins-7.2.5.tgz", - "integrity": "sha512-w+5ccu1IxBHgyQk9CPFKLZOk8yZQEyTjbJwOzESK1eR7QwosbcsLkN1c1WWUZYiCXwORu3UTwJYll4+X2xxJhQ==", - "dependencies": { - "@expo/config-types": "^49.0.0-alpha.1", - "@expo/json-file": "~8.2.37", - "@expo/plist": "^0.0.20", - "@expo/sdk-runtime-versions": "^1.0.0", - "@react-native/normalize-color": "^2.0.0", - "chalk": "^4.1.2", - "debug": "^4.3.1", - "find-up": "~5.0.0", - "getenv": "^1.0.0", - "glob": "7.1.6", - "resolve-from": "^5.0.0", - "semver": "^7.5.3", - "slash": "^3.0.0", - "xcode": "^3.0.1", - "xml2js": "0.6.0" - } - }, - "node_modules/expo-linking/node_modules/@expo/config-types": { - "version": "49.0.0", - "resolved": "https://registry.npmjs.org/@expo/config-types/-/config-types-49.0.0.tgz", - "integrity": "sha512-8eyREVi+K2acnMBe/rTIu1dOfyR2+AMnTLHlut+YpMV9OZPdeKV0Bs9BxAewGqBA2slslbQ9N39IS2CuTKpXkA==" - }, - "node_modules/expo-linking/node_modules/@expo/json-file": { - "version": "8.2.37", - "resolved": "https://registry.npmjs.org/@expo/json-file/-/json-file-8.2.37.tgz", - "integrity": "sha512-YaH6rVg11JoTS2P6LsW7ybS2CULjf40AbnAHw2F1eDPuheprNjARZMnyHFPkKv7GuxCy+B9GPcbOKgc4cgA80Q==", - "dependencies": { - "@babel/code-frame": "~7.10.4", - "json5": "^2.2.2", - "write-file-atomic": "^2.3.0" - } - }, - "node_modules/expo-linking/node_modules/@expo/plist": { - "version": "0.0.20", - "resolved": "https://registry.npmjs.org/@expo/plist/-/plist-0.0.20.tgz", - "integrity": "sha512-UXQ4LXCfTZ580LDHGJ5q62jSTwJFFJ1GqBu8duQMThiHKWbMJ+gajJh6rsB6EJ3aLUr9wcauxneL5LVRFxwBEA==", - "dependencies": { - "@xmldom/xmldom": "~0.7.7", - "base64-js": "^1.2.3", - "xmlbuilder": "^14.0.0" - } - }, - "node_modules/expo-linking/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/expo-linking/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/expo-linking/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/expo-linking/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "node_modules/expo-linking/node_modules/expo-constants": { - "version": "14.4.2", - "resolved": "https://registry.npmjs.org/expo-constants/-/expo-constants-14.4.2.tgz", - "integrity": "sha512-nOB122DOAjk+KrJT69lFQAoYVQGQjFHSigCPVBzVdko9S1xGsfiOH9+X5dygTsZTIlVLpQJDdmZ7ONiv3i+26w==", - "dependencies": { - "@expo/config": "~8.1.0", - "uuid": "^3.3.2" - }, - "peerDependencies": { - "expo": "*" - } - }, - "node_modules/expo-linking/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/expo-linking/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/expo-linking/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/expo-linking/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/expo-linking/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/expo-linking/node_modules/semver": { - "version": "7.5.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz", - "integrity": "sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/expo-linking/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/expo-linking/node_modules/write-file-atomic": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", - "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/expo-linking/-/expo-linking-6.2.2.tgz", + "integrity": "sha512-FEe6lP4f7xFT/vjoHRG+tt6EPVtkEGaWNK1smpaUevmNdyCJKqW0PDB8o8sfG6y7fly8ULe8qg3HhKh5J7aqUQ==", "dependencies": { - "graceful-fs": "^4.1.11", - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.2" + "expo-constants": "~15.4.3", + "invariant": "^2.2.4" } }, - "node_modules/expo-linking/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, "node_modules/expo-manifests": { "version": "0.13.2", "resolved": "https://registry.npmjs.org/expo-manifests/-/expo-manifests-0.13.2.tgz", @@ -12712,9 +12476,9 @@ "integrity": "sha512-ddQEtCOgYHTLlFUe/yH67dDBIoct5VIULthyT3LRJbEwdpzAgueKsX2FYK02ldh440V87PWKCamh7R9evk1rrg==" }, "node_modules/expo-store-review": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/expo-store-review/-/expo-store-review-6.4.0.tgz", - "integrity": "sha512-aD06KSOO9syeecaP9NfJO++FzmfQjg49HY7qeUQ9r826YqswW/FPAcnXY0RJLhfJTqeAPRSl/xzPLZA5vwdqLQ==", + "version": "6.8.3", + "resolved": "https://registry.npmjs.org/expo-store-review/-/expo-store-review-6.8.3.tgz", + "integrity": "sha512-RuZ1P0AO9BT37FnVQgK93KtxGoriLfG0uH0HqYyWdN2GQAKHtm1Ucu6sfwrHkdXpOXs+xqbTd669k4D6HC/+0w==", "peerDependencies": { "expo": "*" } @@ -13368,6 +13132,7 @@ "version": "1.2.4", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dev": true, "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2", @@ -13576,6 +13341,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, "dependencies": { "get-intrinsic": "^1.1.3" }, @@ -13637,6 +13403,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, "dependencies": { "es-define-property": "^1.0.0" }, @@ -13648,6 +13415,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "dev": true, "engines": { "node": ">= 0.4" }, @@ -13659,6 +13427,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, "engines": { "node": ">= 0.4" }, @@ -18473,6 +18242,7 @@ "version": "1.13.1", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -19224,20 +18994,6 @@ "qrcode-terminal": "bin/qrcode-terminal.js" } }, - "node_modules/qs": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.12.0.tgz", - "integrity": "sha512-trVZiI6RMOkO476zLGaBIzszOdFPnCCXHPG9kn0yuS1uz6xdVxPfZdB3vUig9pxPFDM9BRAgz/YUIVQ1/vuiUg==", - "dependencies": { - "side-channel": "^1.0.6" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/query-string": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/query-string/-/query-string-7.1.3.tgz", @@ -19258,7 +19014,8 @@ "node_modules/querystringify": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "dev": true }, "node_modules/queue": { "version": "6.0.2", @@ -19396,9 +19153,9 @@ } }, "node_modules/react-native": { - "version": "0.73.5", - "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.73.5.tgz", - "integrity": "sha512-iHgDArmF4CrhL0qTj+Rn+CBN5pZWUL9lUGl8ub+V9Hwu/vnzQQh8rTMVSwVd2sV6N76KjpE5a4TfIAHkpIHhKg==", + "version": "0.73.6", + "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.73.6.tgz", + "integrity": "sha512-oqmZe8D2/VolIzSPZw+oUd6j/bEmeRHwsLn1xLA5wllEYsZ5zNuMsDus235ONOnCRwexqof/J3aztyQswSmiaA==", "dependencies": { "@jest/create-cache-key-function": "^29.6.3", "@react-native-community/cli": "12.3.6", @@ -20320,7 +20077,8 @@ "node_modules/requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "dev": true }, "node_modules/reselect": { "version": "4.1.8", @@ -20718,6 +20476,7 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", @@ -20805,6 +20564,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dev": true, "dependencies": { "call-bind": "^1.0.7", "es-errors": "^1.3.0", @@ -22111,6 +21871,7 @@ "version": "1.5.10", "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "dev": true, "dependencies": { "querystringify": "^2.1.1", "requires-port": "^1.0.0" @@ -22153,15 +21914,6 @@ "base64-arraybuffer": "^1.0.2" } }, - "node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", - "bin": { - "uuid": "bin/uuid" - } - }, "node_modules/v8-to-istanbul": { "version": "9.2.0", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz", diff --git a/package.json b/package.json index c7b772d7..97ab0fba 100644 --- a/package.json +++ b/package.json @@ -27,13 +27,13 @@ "@reduxjs/toolkit": "^1.9.3", "colorsheet": "^1.0.5", "dotenv": "^16.0.3", - "expo": "^50.0.13", + "expo": "~50.0.14", "expo-application": "~5.8.3", "expo-blur": "~12.9.2", "expo-build-properties": "~0.11.1", "expo-constants": "~15.4.5", "expo-crypto": "~12.8.1", - "expo-dev-client": "~3.3.10", + "expo-dev-client": "~3.3.11", "expo-device": "~5.9.3", "expo-haptics": "~12.8.1", "expo-image": "~1.10.6", @@ -50,7 +50,7 @@ "react": "18.2.0", "react-dom": "18.2.0", "react-moment": "^1.1.3", - "react-native": "0.73.5", + "react-native": "0.73.6", "react-native-animated-pagination-dots": "^0.1.73", "react-native-elements": "^3.4.2", "react-native-gesture-handler": "~2.14.0", @@ -74,8 +74,8 @@ "redux-persist": "^6.0.0", "semver": "^7.5.4", "typescript": "^5.1.6", - "expo-store-review": "~6.4.0", - "expo-linking": "~5.0.2" + "expo-store-review": "~6.8.3", + "expo-linking": "~6.2.2" }, "devDependencies": { "@babel/core": "^7.19.3", From 2d8cba0aabaf4b29009e3b85b08fae429d40b30a Mon Sep 17 00:00:00 2001 From: Justin Wyne <1986068+wyne@users.noreply.github.com> Date: Wed, 27 Mar 2024 17:27:01 -0700 Subject: [PATCH 016/150] easignore --- .easignore | 2 ++ .gitignore | 5 +++-- 2 files changed, 5 insertions(+), 2 deletions(-) create mode 100644 .easignore diff --git a/.easignore b/.easignore new file mode 100644 index 00000000..d986adfd --- /dev/null +++ b/.easignore @@ -0,0 +1,2 @@ +assets-src/ +assets-stores/ diff --git a/.gitignore b/.gitignore index 5eb80c4e..29ce2cd9 100644 --- a/.gitignore +++ b/.gitignore @@ -5,7 +5,8 @@ *.key *.mobileprovision *.orig.* - +*.ipa +*.apk # Ignore iOS and Android builds @@ -50,4 +51,4 @@ yarn-error.* # typescript *.tsbuildinfo -# @end expo-cli \ No newline at end of file +# @end expo-cli From 378dc01e8df5ba7948a70d8efa04b37d9de5ba64 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 28 Mar 2024 03:10:46 +0000 Subject: [PATCH 017/150] Bump semver from 7.5.4 to 7.6.0 Bumps [semver](https://github.com/npm/node-semver) from 7.5.4 to 7.6.0. - [Release notes](https://github.com/npm/node-semver/releases) - [Changelog](https://github.com/npm/node-semver/blob/main/CHANGELOG.md) - [Commits](https://github.com/npm/node-semver/compare/v7.5.4...v7.6.0) --- updated-dependencies: - dependency-name: semver dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- package-lock.json | 38 ++++---------------------------------- package.json | 2 +- 2 files changed, 5 insertions(+), 35 deletions(-) diff --git a/package-lock.json b/package-lock.json index 01fedfe5..e5b849de 100644 --- a/package-lock.json +++ b/package-lock.json @@ -71,7 +71,7 @@ "react-navigation-stack": "^2.10.4", "react-redux": "^8.0.2", "redux-persist": "^6.0.0", - "semver": "^7.5.4", + "semver": "^7.6.0", "typescript": "^5.1.6" }, "devDependencies": { @@ -2613,17 +2613,6 @@ "node": ">=8" } }, - "node_modules/@expo/cli/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@expo/cli/node_modules/picomatch": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-3.0.1.tgz", @@ -2635,20 +2624,6 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/@expo/cli/node_modules/semver": { - "version": "7.5.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz", - "integrity": "sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@expo/cli/node_modules/source-map-support": { "version": "0.5.21", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", @@ -2669,11 +2644,6 @@ "node": ">=8" } }, - "node_modules/@expo/cli/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, "node_modules/@expo/code-signing-certificates": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/@expo/code-signing-certificates/-/code-signing-certificates-0.0.5.tgz", @@ -20356,9 +20326,9 @@ } }, "node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dependencies": { "lru-cache": "^6.0.0" }, diff --git a/package.json b/package.json index 97ab0fba..133a26ec 100644 --- a/package.json +++ b/package.json @@ -72,7 +72,7 @@ "react-navigation-stack": "^2.10.4", "react-redux": "^8.0.2", "redux-persist": "^6.0.0", - "semver": "^7.5.4", + "semver": "^7.6.0", "typescript": "^5.1.6", "expo-store-review": "~6.8.3", "expo-linking": "~6.2.2" From fea1e3fc2a3a2bf1d3a853785aa0193a49cc939b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 28 Mar 2024 03:11:40 +0000 Subject: [PATCH 018/150] Bump typescript from 5.3.3 to 5.4.3 Bumps [typescript](https://github.com/Microsoft/TypeScript) from 5.3.3 to 5.4.3. - [Release notes](https://github.com/Microsoft/TypeScript/releases) - [Changelog](https://github.com/microsoft/TypeScript/blob/main/azure-pipelines.release.yml) - [Commits](https://github.com/Microsoft/TypeScript/compare/v5.3.3...v5.4.3) --- updated-dependencies: - dependency-name: typescript dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 01fedfe5..66e23726 100644 --- a/package-lock.json +++ b/package-lock.json @@ -72,7 +72,7 @@ "react-redux": "^8.0.2", "redux-persist": "^6.0.0", "semver": "^7.5.4", - "typescript": "^5.1.6" + "typescript": "^5.4.3" }, "devDependencies": { "@babel/core": "^7.19.3", @@ -21684,9 +21684,9 @@ } }, "node_modules/typescript": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", - "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.3.tgz", + "integrity": "sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg==", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" diff --git a/package.json b/package.json index 97ab0fba..cca8c25f 100644 --- a/package.json +++ b/package.json @@ -73,7 +73,7 @@ "react-redux": "^8.0.2", "redux-persist": "^6.0.0", "semver": "^7.5.4", - "typescript": "^5.1.6", + "typescript": "^5.4.3", "expo-store-review": "~6.8.3", "expo-linking": "~6.2.2" }, From 4c3f756e4c6b014e6601ef4b5a9c27b310decd49 Mon Sep 17 00:00:00 2001 From: Justin Wyne <1986068+wyne@users.noreply.github.com> Date: Wed, 27 Mar 2024 22:53:05 -0700 Subject: [PATCH 019/150] Empty state for no games --- src/components/Buttons/NewGameButton.tsx | 6 +++-- .../PlayerTiles/AdditionTile/Helpers.ts | 4 ++-- src/screens/ListScreen.tsx | 24 +++++++++---------- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/components/Buttons/NewGameButton.tsx b/src/components/Buttons/NewGameButton.tsx index b5f16a5b..5cc7eb2c 100644 --- a/src/components/Buttons/NewGameButton.tsx +++ b/src/components/Buttons/NewGameButton.tsx @@ -16,7 +16,7 @@ interface Props { const NewGameButton: React.FunctionComponent = ({ navigation }) => { const dispatch = useAppDispatch(); - const gameList = useAppSelector(state => selectAllGames(state)); + const gameList = useAppSelector(selectAllGames); const playerNumberOptions = [...Array.from(Array(12).keys(), n => n + 1)]; @@ -28,9 +28,11 @@ const NewGameButton: React.FunctionComponent = ({ navigation }) => { }); const addGameHandler = async (playerCount: number) => { + console.log('games', gameList); + dispatch( asyncCreateGame({ - gameCount: gameList.length + 1, + gameCount: gameList.length, playerCount: playerCount }) ).then(() => { diff --git a/src/components/PlayerTiles/AdditionTile/Helpers.ts b/src/components/PlayerTiles/AdditionTile/Helpers.ts index 292bfb9c..21bcf45d 100644 --- a/src/components/PlayerTiles/AdditionTile/Helpers.ts +++ b/src/components/PlayerTiles/AdditionTile/Helpers.ts @@ -1,4 +1,4 @@ -import { ZoomIn, ZoomOut , Layout, Easing , withTiming } from 'react-native-reanimated'; +import { Easing, LinearTransition, ZoomIn, ZoomOut, withTiming } from 'react-native-reanimated'; /** * The duration of the animation in milliseconds. @@ -18,7 +18,7 @@ export const exitingAnimation = ZoomOut.duration(animationDuration); /** * The easing and duration of the layout animation. */ -export const layoutAnimation = Layout.easing(Easing.ease).duration(animationDuration); +export const layoutAnimation = LinearTransition.easing(Easing.ease).duration(animationDuration); export const singleLineScoreSizeMultiplier = 1.2; diff --git a/src/screens/ListScreen.tsx b/src/screens/ListScreen.tsx index 3cc32b13..bd96d221 100644 --- a/src/screens/ListScreen.tsx +++ b/src/screens/ListScreen.tsx @@ -4,11 +4,11 @@ import { ParamListBase } from '@react-navigation/native'; import { NativeStackNavigationProp } from '@react-navigation/native-stack'; import { BlurView } from 'expo-blur'; import { StyleSheet, Text, View } from 'react-native'; -import Animated, { Layout, Easing } from 'react-native-reanimated'; +import Animated, { Easing, LinearTransition } from 'react-native-reanimated'; import { SafeAreaView } from 'react-native-safe-area-context'; -import { asyncCreateGame, selectAllGames } from '../../redux/GamesSlice'; -import { useAppSelector, useAppDispatch } from '../../redux/hooks'; +import { selectAllGames } from '../../redux/GamesSlice'; +import { useAppDispatch, useAppSelector } from '../../redux/hooks'; import { setOnboardedVersion } from '../../redux/SettingsSlice'; import GameListItem from '../components/GameListItem'; @@ -20,24 +20,21 @@ const ListScreen: React.FunctionComponent = ({ navigation }) => { const gameList = useAppSelector(state => selectAllGames(state)); const dispatch = useAppDispatch(); - // If no games, create one and navigate to it useEffect(() => { dispatch(setOnboardedVersion()); - - if (gameList.length == 0) { - dispatch(asyncCreateGame({ gameCount: gameList.length + 1, playerCount: 2 })).then(() => { - setTimeout(() => { - navigation.navigate("Game"); - }, 500); - }); - } }, [gameList.length]); return ( } - itemLayoutAnimation={Layout.easing(Easing.ease)} + itemLayoutAnimation={LinearTransition.easing(Easing.ease)} + ListEmptyComponent={ + <> + No Games + Tap the + button above to create a new game. + + } style={styles.list} data={gameList} renderItem={({ item, index }) => @@ -50,6 +47,7 @@ const ListScreen: React.FunctionComponent = ({ navigation }) => { position: 'absolute', bottom: 0, left: 0, right: 0, height: 60, justifyContent: 'flex-start', alignItems: 'center', borderTopWidth: 1, borderColor: '#ccc', + display: gameList.length > 0 ? undefined : 'none', }}> Long press for more options. From 23484b15dbeb28ab43f80a9b9ddd07d11b487bc0 Mon Sep 17 00:00:00 2001 From: Justin Wyne <1986068+wyne@users.noreply.github.com> Date: Wed, 27 Mar 2024 23:35:24 -0700 Subject: [PATCH 020/150] Sort players by totals --- redux/GamesSlice.ts | 19 +++++++++++++++++++ redux/PlayersSlice.ts | 12 +++++++++++- src/components/Rounds.tsx | 7 ++++--- src/components/ScoreLog/PlayerNameColumn.tsx | 15 +++++++++++---- src/components/ScoreLog/RoundScoreColumn.tsx | 8 ++++++-- src/components/ScoreLog/TotalScoreColumn.tsx | 11 ++++++++--- 6 files changed, 59 insertions(+), 13 deletions(-) diff --git a/redux/GamesSlice.ts b/redux/GamesSlice.ts index 96d490ec..260434f0 100644 --- a/redux/GamesSlice.ts +++ b/redux/GamesSlice.ts @@ -118,6 +118,25 @@ export const selectSortedPlayers = createSelector( } ); +export const selectPlayersByScore = createSelector( + [ + selectAllPlayers, + (state: RootState) => state.settings.currentGameId ? state.games.entities[state.settings.currentGameId] : undefined + ], + (players: ScoreState[], currentGame: GameState | undefined) => { + if (!currentGame) return []; + + return [...players] + .filter(player => currentGame.playerIds?.includes(player.id)) + .sort((a, b) => { + const totalScoreA = a.scores.reduce((acc, score) => acc + score, 0); + const totalScoreB = b.scores.reduce((acc, score) => acc + score, 0); + return totalScoreB - totalScoreA; + }) + .map(player => player.id); + } +); + export const { updateGame, roundNext, diff --git a/redux/PlayersSlice.ts b/redux/PlayersSlice.ts index cadba39d..268306c0 100644 --- a/redux/PlayersSlice.ts +++ b/redux/PlayersSlice.ts @@ -1,5 +1,7 @@ import crashlytics from '@react-native-firebase/crashlytics'; -import { createSlice, PayloadAction, createEntityAdapter } from '@reduxjs/toolkit'; +import { PayloadAction, createEntityAdapter, createSelector, createSlice } from '@reduxjs/toolkit'; + +import { RootState } from './store'; type RoundIndex = number; @@ -56,6 +58,14 @@ interface PlayersSlice { players: typeof initialState; } +export const selectPlayersByIds = createSelector( + [ + (state: RootState) => state.players.entities, + (_, playerIds: string[]) => playerIds, + ], + (players, playerIds) => playerIds.map(id => players[id]) +); + export const { updatePlayer, removePlayer, diff --git a/src/components/Rounds.tsx b/src/components/Rounds.tsx index 53c24f97..150c2d06 100644 --- a/src/components/Rounds.tsx +++ b/src/components/Rounds.tsx @@ -4,7 +4,7 @@ import { ParamListBase } from '@react-navigation/native'; import { NativeStackNavigationProp } from '@react-navigation/native-stack'; import { View, StyleSheet, ScrollView, Platform, LayoutChangeEvent } from 'react-native'; -import { selectGameById } from '../../redux/GamesSlice'; +import { selectGameById, selectPlayersByScore } from '../../redux/GamesSlice'; import { useAppSelector } from '../../redux/hooks'; import PlayerNameColumn from './ScoreLog/PlayerNameColumn'; @@ -57,14 +57,15 @@ const Rounds: React.FunctionComponent = ({ }) => { return ( - - + + {roundsIterator.map((item, round) => ( onLayoutHandler(e, round)}> diff --git a/src/components/ScoreLog/PlayerNameColumn.tsx b/src/components/ScoreLog/PlayerNameColumn.tsx index 011ea6a7..925c568a 100644 --- a/src/components/ScoreLog/PlayerNameColumn.tsx +++ b/src/components/ScoreLog/PlayerNameColumn.tsx @@ -3,17 +3,24 @@ import React from 'react'; import { StyleSheet, Text, View } from 'react-native'; import { Icon } from 'react-native-elements/dist/icons/Icon'; -import { selectSortedPlayers } from '../../../redux/GamesSlice'; import { useAppSelector } from '../../../redux/hooks'; +import { selectPlayersByIds } from '../../../redux/PlayersSlice'; import { selectCurrentGame } from '../../../redux/selectors'; +import { RootState } from '../../../redux/store'; import { palette, systemBlue } from '../../constants'; -const PlayerNameColumn: React.FunctionComponent = ({ }) => { +interface Props { + sortSelector: (state: RootState) => string[]; +} + +const PlayerNameColumn: React.FunctionComponent = ({ sortSelector }) => { const currentGame = useAppSelector(selectCurrentGame); if (currentGame == undefined) return null; - const players = useAppSelector(selectSortedPlayers); + const sortedPlayerIds = useAppSelector(sortSelector); + + const players = useAppSelector((state: RootState) => selectPlayersByIds(state, sortedPlayerIds)); if (players == undefined) return null; @@ -30,7 +37,7 @@ const PlayerNameColumn: React.FunctionComponent = ({ }) => { {player.playerName} + >{player?.playerName} ))} diff --git a/src/components/ScoreLog/RoundScoreColumn.tsx b/src/components/ScoreLog/RoundScoreColumn.tsx index b0ed0068..62c78d5c 100644 --- a/src/components/ScoreLog/RoundScoreColumn.tsx +++ b/src/components/ScoreLog/RoundScoreColumn.tsx @@ -6,6 +6,7 @@ import { Text, TouchableWithoutFeedback, View } from 'react-native'; import { updateGame } from '../../../redux/GamesSlice'; import { useAppDispatch, useAppSelector } from '../../../redux/hooks'; import { selectCurrentGame } from '../../../redux/selectors'; +import { RootState } from '../../../redux/store'; import RoundScoreCell from './RoundScoreCell'; @@ -13,9 +14,10 @@ interface Props { round: number; isCurrentRound: boolean; disabled?: boolean; + sortSelector: (state: RootState) => string[]; } -const RoundScoreColumn: React.FunctionComponent = ({ round, isCurrentRound, disabled = false }) => { +const RoundScoreColumn: React.FunctionComponent = ({ round, isCurrentRound, disabled = false, sortSelector }) => { const dispatch = useAppDispatch(); const currentGameId = useAppSelector(state => state.settings.currentGameId); @@ -23,6 +25,8 @@ const RoundScoreColumn: React.FunctionComponent = ({ round, isCurrentRoun if (typeof currentGame == 'undefined') return null; + const sortedPlayerIds = useAppSelector(sortSelector); + const onPressHandler = useCallback(async () => { if (disabled || !currentGameId) return; @@ -61,7 +65,7 @@ const RoundScoreColumn: React.FunctionComponent = ({ round, isCurrentRoun }}> {round + 1} - {currentGame.playerIds.map((playerId, playerIndex) => ( + {sortedPlayerIds.map((playerId, playerIndex) => ( ))} diff --git a/src/components/ScoreLog/TotalScoreColumn.tsx b/src/components/ScoreLog/TotalScoreColumn.tsx index c0a6b49c..2fb0037f 100644 --- a/src/components/ScoreLog/TotalScoreColumn.tsx +++ b/src/components/ScoreLog/TotalScoreColumn.tsx @@ -4,22 +4,27 @@ import { StyleSheet, Text, View } from 'react-native'; import { useAppSelector } from '../../../redux/hooks'; import { selectCurrentGame } from '../../../redux/selectors'; +import { RootState } from '../../../redux/store'; import TotalScoreCell from './TotalScoreCell'; -const TotalScoreColumn = ({ }) => { +interface Props { + sortSelector: (state: RootState) => string[]; +} + +const TotalScoreColumn: React.FunctionComponent = ({ sortSelector }) => { const currentGame = useAppSelector(selectCurrentGame); if (typeof currentGame == 'undefined') return null; - const playerIds = currentGame.playerIds; + const sortedPlayerIds = useAppSelector(sortSelector); return ( Total - {playerIds.map((playerId) => ( + {sortedPlayerIds.map((playerId) => ( ))} From 9af62d6b7130c904187fa6c005480f6b4374c967 Mon Sep 17 00:00:00 2001 From: Justin Wyne <1986068+wyne@users.noreply.github.com> Date: Wed, 27 Mar 2024 23:48:53 -0700 Subject: [PATCH 021/150] Get correct player color when sorted by total --- src/components/ScoreLog/PlayerNameColumn.tsx | 12 +++++++++++- src/components/ScoreLog/TotalScoreColumn.tsx | 2 +- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/components/ScoreLog/PlayerNameColumn.tsx b/src/components/ScoreLog/PlayerNameColumn.tsx index 925c568a..2bb22080 100644 --- a/src/components/ScoreLog/PlayerNameColumn.tsx +++ b/src/components/ScoreLog/PlayerNameColumn.tsx @@ -24,6 +24,16 @@ const PlayerNameColumn: React.FunctionComponent = ({ sortSelector }) => { if (players == undefined) return null; + const getPlayerIndex = (playerId: string | undefined) => { + if (playerId == undefined) return -1; + const index = currentGame.playerIds.findIndex((id) => id === playerId); + return index; + }; + + const playerColor = (playerId: string | undefined) => { + return "#" + palette[getPlayerIndex(playerId) % palette.length]; + }; + return ( @@ -34,7 +44,7 @@ const PlayerNameColumn: React.FunctionComponent = ({ sortSelector }) => { color='white' /> {players.map((player, index) => ( - + {player?.playerName} diff --git a/src/components/ScoreLog/TotalScoreColumn.tsx b/src/components/ScoreLog/TotalScoreColumn.tsx index 2fb0037f..dfa08fbd 100644 --- a/src/components/ScoreLog/TotalScoreColumn.tsx +++ b/src/components/ScoreLog/TotalScoreColumn.tsx @@ -22,7 +22,7 @@ const TotalScoreColumn: React.FunctionComponent = ({ sortSelector }) => { return ( - Total + Total ↓ {sortedPlayerIds.map((playerId) => ( From 31075703c19806016c82fa999fec8640fd92b57f Mon Sep 17 00:00:00 2001 From: Justin Wyne <1986068+wyne@users.noreply.github.com> Date: Fri, 29 Mar 2024 21:38:33 -0700 Subject: [PATCH 022/150] Allow toggling of sorting method --- redux/GamesSlice.ts | 40 +--------------- src/components/Rounds.tsx | 22 ++++++--- src/components/ScoreLog/PlayerNameColumn.tsx | 4 +- src/components/ScoreLog/SortHelper.ts | 49 ++++++++++++++++++++ src/components/Sheets/GameSheet.tsx | 11 +++-- src/screens/SettingsScreen.tsx | 20 ++++---- 6 files changed, 86 insertions(+), 60 deletions(-) create mode 100644 src/components/ScoreLog/SortHelper.ts diff --git a/redux/GamesSlice.ts b/redux/GamesSlice.ts index 260434f0..6a8c4d83 100644 --- a/redux/GamesSlice.ts +++ b/redux/GamesSlice.ts @@ -1,10 +1,9 @@ import analytics from '@react-native-firebase/analytics'; -import { createSlice, PayloadAction, createEntityAdapter, createAsyncThunk, createSelector } from '@reduxjs/toolkit'; +import { PayloadAction, createAsyncThunk, createEntityAdapter, createSlice } from '@reduxjs/toolkit'; import * as Crypto from 'expo-crypto'; -import { ScoreState, playerAdd, selectAllPlayers } from './PlayersSlice'; +import { playerAdd } from './PlayersSlice'; import { setCurrentGameId } from './SettingsSlice'; -import { RootState } from './store'; export interface GameState { id: string; @@ -102,41 +101,6 @@ export const asyncCreateGame = createAsyncThunk( } ); -export const selectSortedPlayers = createSelector( - [ - selectAllPlayers, - (state: RootState) => state.settings.currentGameId ? state.games.entities[state.settings.currentGameId] : undefined - ], - (players: ScoreState[], currentGame: GameState | undefined) => { - if (!currentGame) return []; - - return 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 selectPlayersByScore = createSelector( - [ - selectAllPlayers, - (state: RootState) => state.settings.currentGameId ? state.games.entities[state.settings.currentGameId] : undefined - ], - (players: ScoreState[], currentGame: GameState | undefined) => { - if (!currentGame) return []; - - return [...players] - .filter(player => currentGame.playerIds?.includes(player.id)) - .sort((a, b) => { - const totalScoreA = a.scores.reduce((acc, score) => acc + score, 0); - const totalScoreB = b.scores.reduce((acc, score) => acc + score, 0); - return totalScoreB - totalScoreA; - }) - .map(player => player.id); - } -); - export const { updateGame, roundNext, diff --git a/src/components/Rounds.tsx b/src/components/Rounds.tsx index 150c2d06..ef4c9eff 100644 --- a/src/components/Rounds.tsx +++ b/src/components/Rounds.tsx @@ -1,14 +1,16 @@ -import React, { useEffect, useRef, useState, useCallback } from 'react'; +import React, { useCallback, useEffect, useRef, useState } from 'react'; import { ParamListBase } from '@react-navigation/native'; import { NativeStackNavigationProp } from '@react-navigation/native-stack'; -import { View, StyleSheet, ScrollView, Platform, LayoutChangeEvent } from 'react-native'; +import { LayoutChangeEvent, Platform, ScrollView, StyleSheet, View } from 'react-native'; +import { TouchableOpacity } from 'react-native-gesture-handler'; -import { selectGameById, selectPlayersByScore } from '../../redux/GamesSlice'; +import { selectGameById } from '../../redux/GamesSlice'; import { useAppSelector } from '../../redux/hooks'; import PlayerNameColumn from './ScoreLog/PlayerNameColumn'; import RoundScoreColumn from './ScoreLog/RoundScoreColumn'; +import { sortSelectors } from './ScoreLog/SortHelper'; import TotalScoreColumn from './ScoreLog/TotalScoreColumn'; interface Props { @@ -55,17 +57,25 @@ const Rounds: React.FunctionComponent = ({ }) => { const roundsIterator = [...Array(roundTotal).keys()]; + const [sortSelectorIndex, setSortSelectorIndex] = useState(0); + + const nextSort = () => { + setSortSelectorIndex((sortSelectorIndex + 1) % sortSelectors.length); + }; + return ( - - + + + + {roundsIterator.map((item, round) => ( onLayoutHandler(e, round)}> diff --git a/src/components/ScoreLog/PlayerNameColumn.tsx b/src/components/ScoreLog/PlayerNameColumn.tsx index 2bb22080..c9713c91 100644 --- a/src/components/ScoreLog/PlayerNameColumn.tsx +++ b/src/components/ScoreLog/PlayerNameColumn.tsx @@ -3,6 +3,7 @@ import React from 'react'; import { StyleSheet, Text, View } from 'react-native'; import { Icon } from 'react-native-elements/dist/icons/Icon'; +import { SortSelector } from '../../../redux/GamesSlice'; import { useAppSelector } from '../../../redux/hooks'; import { selectPlayersByIds } from '../../../redux/PlayersSlice'; import { selectCurrentGame } from '../../../redux/selectors'; @@ -10,7 +11,7 @@ import { RootState } from '../../../redux/store'; import { palette, systemBlue } from '../../constants'; interface Props { - sortSelector: (state: RootState) => string[]; + sortSelector: SortSelector; } const PlayerNameColumn: React.FunctionComponent = ({ sortSelector }) => { @@ -43,6 +44,7 @@ const PlayerNameColumn: React.FunctionComponent = ({ sortSelector }) => { size={19} color='white' /> + {players.map((player, index) => ( state.settings.currentGameId ? state.games.entities[state.settings.currentGameId] : undefined + ], + (players: ScoreState[], currentGame: GameState | undefined) => { + if (!currentGame) return []; + + return 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); + }) + .map(player => player.id); + } +); + +export const selectPlayerIdsByScore: SortSelector = createSelector( + [ + selectAllPlayers, + (state: RootState) => state.settings.currentGameId ? state.games.entities[state.settings.currentGameId] : undefined + ], + (players: ScoreState[], currentGame: GameState | undefined) => { + if (!currentGame) return []; + + return [...players] + .filter(player => currentGame.playerIds?.includes(player.id)) + .sort((a, b) => { + const totalScoreA = a.scores.reduce((acc, score) => acc + score, 0); + const totalScoreB = b.scores.reduce((acc, score) => acc + score, 0); + return totalScoreB - totalScoreA; + }) + .map(player => player.id); + } +); + +export interface SortSelector { + (state: RootState): string[]; +} +export const sortSelectors: SortSelector[] = [ + selectPlayerIdsByScore, + selectPlayerIdsByIndex, +]; diff --git a/src/components/Sheets/GameSheet.tsx b/src/components/Sheets/GameSheet.tsx index 53037447..2644f153 100644 --- a/src/components/Sheets/GameSheet.tsx +++ b/src/components/Sheets/GameSheet.tsx @@ -5,16 +5,17 @@ import { ParamListBase, useIsFocused } from '@react-navigation/native'; import { NativeStackNavigationProp } from '@react-navigation/native-stack'; import { Alert, Platform, StyleSheet, Text, TouchableWithoutFeedback, View } from 'react-native'; import { Button } from 'react-native-elements'; -import Animated, { Extrapolate, FadeIn, Layout, interpolate, useAnimatedStyle, useSharedValue } from 'react-native-reanimated'; +import Animated, { Extrapolate, FadeIn, interpolate, Layout, useAnimatedStyle, useSharedValue } from 'react-native-reanimated'; import { SafeAreaView } from 'react-native-safe-area-context'; -import { selectSortedPlayers, updateGame } from '../../../redux/GamesSlice'; +import { updateGame } from '../../../redux/GamesSlice'; import { useAppDispatch, useAppSelector } from '../../../redux/hooks'; import { updatePlayer } from '../../../redux/PlayersSlice'; import { selectCurrentGame } from '../../../redux/selectors'; import { systemBlue } from '../../constants'; import BigButton from '../BigButtons/BigButton'; import Rounds from '../Rounds'; +import { selectPlayerIdsByIndex } from '../ScoreLog/SortHelper'; import { useGameSheetContext } from './GameSheetContext'; @@ -39,7 +40,7 @@ const GameSheet: React.FunctionComponent = ({ navigation, containerHeight if (currentGame == undefined) return null; - const players = useAppSelector(selectSortedPlayers); + const playerIds = useAppSelector(selectPlayerIdsByIndex); // ref const gameSheetRef = useGameSheetContext(); @@ -78,9 +79,9 @@ const GameSheet: React.FunctionComponent = ({ navigation, containerHeight onPress: () => { if (currentGame == undefined) return; - players.forEach((player) => { + playerIds.forEach((playerId) => { dispatch(updatePlayer({ - id: player.id, + id: playerId, changes: { scores: [0], } diff --git a/src/screens/SettingsScreen.tsx b/src/screens/SettingsScreen.tsx index 00b384b3..ee38d2f5 100644 --- a/src/screens/SettingsScreen.tsx +++ b/src/screens/SettingsScreen.tsx @@ -9,7 +9,7 @@ import { Button, Icon } from 'react-native-elements'; import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view'; import Animated, { Layout } from 'react-native-reanimated'; -import { selectSortedPlayers, updateGame } from '../../redux/GamesSlice'; +import { selectPlayerIdsByIndex, updateGame } from '../../redux/GamesSlice'; import { useAppDispatch, useAppSelector } from '../../redux/hooks'; import { playerAdd } from '../../redux/PlayersSlice'; import { selectCurrentGame } from '../../redux/selectors'; @@ -36,7 +36,7 @@ const SettingsScreen: React.FunctionComponent = ({ }) => { if (typeof currentGameId == 'undefined') return null; const currentGame = useAppSelector(selectCurrentGame); - const players = useAppSelector(selectSortedPlayers); + const playerIds = useAppSelector(selectPlayerIdsByIndex); const maxPlayers = 12; @@ -47,7 +47,7 @@ const SettingsScreen: React.FunctionComponent = ({ }) => { dispatch(playerAdd({ id: newPlayerId, - playerName: `Player ${players.length + 1}`, + playerName: `Player ${playerIds.length + 1}`, scores: [0], })); @@ -62,7 +62,7 @@ const SettingsScreen: React.FunctionComponent = ({ }) => { await analytics().logEvent('add_player', { game_id: currentGameId, - player_count: players.length + 1, + player_count: playerIds.length + 1, }); }; @@ -76,24 +76,24 @@ const SettingsScreen: React.FunctionComponent = ({ }) => { Player Names - {players.map((player, index) => ( + {playerIds.map((playerId, index) => ( ))} - {players.length < maxPlayers && + {playerIds.length < maxPlayers &&