Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Redux #39

Open
wants to merge 83 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
83 commits
Select commit Hold shift + click to select a range
2a76cb4
Refactor configureStore
amitchellunicef Dec 20, 2023
72a7989
Refactor configureStore 2
amitchellunicef Dec 21, 2023
884f097
Move original redux into common sub folder
amitchellunicef Dec 22, 2023
73d0e68
Rename actions as commonActions
amitchellunicef Dec 22, 2023
1b06594
Rename selectors as commonSelectors
amitchellunicef Dec 22, 2023
b4bdc0d
Rename useSelector
amitchellunicef Dec 22, 2023
0325f48
Move redux helps
amitchellunicef Dec 22, 2023
3b332c4
Rename common redux types
amitchellunicef Dec 22, 2023
30a5b68
Move redux helpers
amitchellunicef Dec 22, 2023
de554d3
Add secure store code
amitchellunicef Dec 22, 2023
fb968fe
Rename commonRootSaga
amitchellunicef Dec 22, 2023
29c0af8
Move commonStore config
amitchellunicef Dec 22, 2023
41cef71
Fix misc imports
amitchellunicef Dec 22, 2023
8e30776
Rename secureRootSaga
amitchellunicef Dec 22, 2023
ac772e1
Add StoreCoordinator
amitchellunicef Dec 22, 2023
af6f3d1
Prevent crash on store change
amitchellunicef Dec 22, 2023
dcdbbda
Add sha256 hashing
amitchellunicef Dec 27, 2023
127889a
Multiple offline users WIP
amitchellunicef Dec 28, 2023
6dd0b7e
Store coordination POC
amitchellunicef Dec 29, 2023
ba03a38
Switch store on key change POC
amitchellunicef Dec 29, 2023
4908afa
Trigger store change via PasswordRequestScreen
amitchellunicef Jan 1, 2024
d39ad4a
Switch stores on login success
amitchellunicef Jan 1, 2024
3e027a2
Use salt when hashing password
amitchellunicef Jan 1, 2024
47d8f5f
Remove redundant 'secure' store logic
amitchellunicef Jan 2, 2024
1c2ae0b
Remove unnecessary /common folder
amitchellunicef Jan 2, 2024
d12d813
Revert 'Common' naming
amitchellunicef Jan 2, 2024
bb58050
Remove unused store context
amitchellunicef Jan 2, 2024
3c3cb3e
Rename storeCredentials
amitchellunicef Jan 2, 2024
8cb95b6
Check store username unique during signup
amitchellunicef Jan 2, 2024
97bace6
Refactor accessSelectors
amitchellunicef Jan 2, 2024
7dc44c5
Add StoreSwitch WIP
amitchellunicef Jan 2, 2024
9f43ff2
Fix background
amitchellunicef Jan 2, 2024
16508d4
Trigger store switch from splash screen
amitchellunicef Jan 2, 2024
aaeb84f
Refactor to reduce number of actions needed
amitchellunicef Jan 3, 2024
93fd7d7
Login offline
amitchellunicef Jan 3, 2024
eee2822
Migrate store with interval completion check
amitchellunicef Jan 3, 2024
b5d8abb
Refactor StoreCoordinator with useReducer
amitchellunicef Jan 4, 2024
9f53992
Type assert to remove @ts-ignore comments
amitchellunicef Jan 4, 2024
4a2a341
Remove unused StoreCoordinator actions
amitchellunicef Jan 4, 2024
5e2c904
Add redux to workspace
amitchellunicef Jan 5, 2024
7bdc1a0
Verify password w/ hash & add to redux blacklists
amitchellunicef Jan 8, 2024
2ed61e1
Rename splash component
amitchellunicef Jan 8, 2024
a88b911
Refactor password formatting
amitchellunicef Jan 8, 2024
d819087
Rename redux keys state & refactor
amitchellunicef Jan 8, 2024
5dfbf13
Migrate data depending on whether store exists
amitchellunicef Jan 8, 2024
82215b9
Save creds for existing user on new device
amitchellunicef Jan 8, 2024
f8124c3
Clear last login from PasswordRequestScreen
amitchellunicef Jan 8, 2024
b992a7c
Switch stores on logout
amitchellunicef Jan 8, 2024
15f6fe0
Delete store
amitchellunicef Jan 9, 2024
3a3b6d7
Refactor StoreSwitchSplash
amitchellunicef Jan 9, 2024
6b9a8d3
Redux store blacklists typesafety
amitchellunicef Jan 9, 2024
5026e1a
Rename loggedOut context
amitchellunicef Jan 9, 2024
85154eb
Add guard statements to StoreSwitchSplash
amitchellunicef Jan 9, 2024
09f75f2
Centralise store switch saga logic
amitchellunicef Jan 11, 2024
a0ae429
Comment
amitchellunicef Jan 12, 2024
8948d77
Refactor password check & request screen
amitchellunicef Jan 12, 2024
70e8220
Improve store exists check
amitchellunicef Jan 12, 2024
99ef28b
Login as legacy user via PasswordRequestScreen WIP
amitchellunicef Jan 13, 2024
e1bd51b
Fix Login as legacy user via PasswordRequestScreen
amitchellunicef Jan 13, 2024
c20b57d
Use dynamic primary store blacklists
amitchellunicef Jan 13, 2024
d65413c
Install react-native-crypto-js
amitchellunicef Jan 15, 2024
06654db
Store userId, secret salt & hash
amitchellunicef Jan 15, 2024
699bedc
Rename secret to answer
amitchellunicef Jan 15, 2024
362bbdc
Fix secret answer hashing & further renaming
amitchellunicef Jan 15, 2024
6aa905c
Refactor type ReduxInstance
amitchellunicef Jan 15, 2024
49d719b
Store encrypted secret keys
amitchellunicef Jan 15, 2024
548d5c3
Improve store saga naming
amitchellunicef Jan 15, 2024
9d782b6
Add comments, remove spread
amitchellunicef Jan 15, 2024
4f71e48
Reset password
amitchellunicef Jan 15, 2024
7e629b5
Return after login failure
amitchellunicef Jan 15, 2024
8484fbb
Edit profile WIP clear out
amitchellunicef Jan 15, 2024
620bddc
Save lastLoggedInUsername on new store setup
amitchellunicef Jan 15, 2024
71c4da3
Migrate all required state on store switch
amitchellunicef Jan 15, 2024
a155d22
Move EditProfile into sub folder
amitchellunicef Jan 17, 2024
7b66286
Install react-native-async-storage
amitchellunicef Jan 17, 2024
56499ce
Refactor using async-storage
amitchellunicef Jan 17, 2024
3b8dc91
Persist common redux state with AsyncStorage
amitchellunicef Jan 17, 2024
4a64033
Edit answer
amitchellunicef Jan 17, 2024
9fcdca9
Edit password
amitchellunicef Jan 17, 2024
65013c6
New answer must be valid
amitchellunicef Jan 17, 2024
aa335f7
Refactor EditProfile logic into hook
amitchellunicef Jan 17, 2024
a553ea3
Refactor
amitchellunicef Jan 17, 2024
ab39e8d
Edit user
amitchellunicef Jan 17, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import { v4 as uuidv4 } from 'uuid'
import moment from 'moment'
import configureStore from 'redux-mock-store'

import _ from 'lodash'
import * as actions from '../../../src/redux/actions'
import { authReducer } from '../../../src/redux/reducers/authReducer'

const middleWares = []
const mockStore = configureStore(middleWares)
Expand Down
19 changes: 10 additions & 9 deletions packages/components/__tests__/redux/reducers/authReducer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import configureStore from 'redux-mock-store'
import _ from 'lodash'
import * as actions from '../../../src/redux/actions'
import { authReducer } from '../../../src/redux/reducers/authReducer'
import { formatPassword } from '../../../src/services/auth'

const middleWares = []
const mockStore = configureStore(middleWares)
Expand All @@ -20,9 +21,9 @@ describe('authReducer', () => {
location: 'Urban',
country: 'ZA',
province: '',
password: _.toLower('00AAaa').trim(),
password: formatPassword('00AAaa'),
secretQuestion: 'favourite_teacher',
secretAnswer: _.toLower('secret_answer').trim(),
secretAnswer: formatPassword('secret_answer'),
}

it('returns the initial state', () => {
Expand All @@ -40,14 +41,14 @@ describe('authReducer', () => {
const expectedType = `CREATE_ACCOUNT_REQUEST`
expect(scopedActions[0].type).toEqual(expectedType)
})
it('Login As guest account', () => {
const action = actions.loginSuccessAsGuestAccount(mockPayload)
const newStore = authReducer(undefined, action)
// Dispatch the action
// it('Login As guest account', () => {
// const action = actions.loginSuccessAsGuestAccount(mockPayload)
// const newStore = authReducer(undefined, action)
// // Dispatch the action

expect(newStore?.user?.name).toEqual(mockPayload.name)
expect(newStore?.user?.isGuest).toEqual(true)
})
// expect(newStore?.user?.name).toEqual(mockPayload.name)
// expect(newStore?.user?.isGuest).toEqual(true)
// })
it('Login Out guest account', () => {
const action = actions.logout()
const newStore = authReducer(undefined, action)
Expand Down
5 changes: 4 additions & 1 deletion packages/components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"dependencies": {
"@oky/core": "*",
"@react-native-community/art": "^1.2.0",
"@react-native-async-storage/async-storage": "1.21.0",
"circular-buffer": "^1.0.2",
"i18n-js": "^3.3.0",
"lodash": "^4.17.11",
Expand Down Expand Up @@ -44,7 +45,9 @@
"tslint-react": "^4.0.0",
"typescript": "4.7.4",
"uuid": "9.0.0",
"react-native-get-random-values": "1.9.0"
"react-native-get-random-values": "1.9.0",
"js-sha256": "0.10.1",
"react-native-crypto-js": "^1.0.0"
},
"devDependencies": {
"@types/lodash": "^4.14.136",
Expand Down
5 changes: 1 addition & 4 deletions packages/components/src/components/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,13 @@ import 'react-native-get-random-values' // Required for uuid package
import React from 'react'
import { AppProvider } from './AppProvider'
import AppNavigator from '../navigators/AppNavigator'
import { configureStore } from '../redux/store'
import { setTopLevelNavigator } from '../services/navigationService'
import { notificationListener } from '../services/notifications'
import { SafeAreaView } from 'react-navigation'
import SplashScreen from 'react-native-splash-screen'
import { Platform } from 'react-native'
import Orientation from 'react-native-orientation-locker'

const { persistor, store } = configureStore()

export default function App() {
React.useEffect(() => {
Orientation.lockToPortrait()
Expand All @@ -28,7 +25,7 @@ export default function App() {
}, [])

return (
<AppProvider store={store} persistor={persistor}>
<AppProvider>
<SafeAreaView
forceInset={{ bottom: 'never' }}
style={{ flex: 1, backgroundColor: '#757575' }}
Expand Down
33 changes: 15 additions & 18 deletions packages/components/src/components/AppProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,24 @@
import React from 'react'
import { Provider as ReduxProvider } from 'react-redux'
import { PersistGate } from 'redux-persist/integration/react'
import { ThemeProvider } from './context/ThemeContext'
import { LocaleProvider } from './context/LocaleContext'
import { DisplayTextProvider } from './context/DisplayTextContext'
import { PredictionProvider } from './context/PredictionProvider'
import { AlertContextProvider } from './context/AlertContext'
import { FlowerProvider } from '../optional/Flower'
import { StoreCoordinator } from '../redux/StoreCoordinator'

export const AppProvider = ({ children, store, persistor }) => (
<ReduxProvider store={store}>
<PersistGate loading={null} persistor={persistor}>
<LocaleProvider>
<ThemeProvider>
<PredictionProvider>
<FlowerProvider>
<AlertContextProvider>
<DisplayTextProvider>{children}</DisplayTextProvider>
</AlertContextProvider>
</FlowerProvider>
</PredictionProvider>
</ThemeProvider>
</LocaleProvider>
</PersistGate>
</ReduxProvider>
export const AppProvider = ({ children }) => (
<StoreCoordinator>
<LocaleProvider>
<ThemeProvider>
<PredictionProvider>
<FlowerProvider>
<AlertContextProvider>
<DisplayTextProvider>{children}</DisplayTextProvider>
</AlertContextProvider>
</FlowerProvider>
</PredictionProvider>
</ThemeProvider>
</LocaleProvider>
</StoreCoordinator>
)
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { FloatingQuestion } from './FloatingQuestion'
import styled from 'styled-components/native'
import { Icon } from '../Icon'
import { HeartAnimation } from './HeartAnimation'
import { useSelector } from '../../../hooks/useSelector'
import { useSelector } from '../../../redux/useSelector'
import * as selectors from '../../../redux/selectors/index'
import moment from 'moment'
import { useDisplayText } from '../../context/DisplayTextContext'
Expand Down
2 changes: 1 addition & 1 deletion packages/components/src/components/common/CalendarList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Image } from 'react-native'
import { CalendarList as DefaultCalendarList, LocaleConfig } from 'react-native-calendars'
import momentTimezone from 'moment-timezone'
import { assets } from '../../assets/index'
import { useSelector } from '../../hooks/useSelector'
import { useSelector } from '../../redux/useSelector'
import * as selectors from '../../redux/selectors'
import { calendarTranslations } from '@oky/core'

Expand Down
2 changes: 1 addition & 1 deletion packages/components/src/components/common/DateBadge.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ import { translate } from '../../i18n'
import { TouchableOpacity } from 'react-native'
import _ from 'lodash'
import moment from 'moment'
import { useSelector } from 'react-redux'
import * as selectors from '../../redux/selectors'
import {
useTodayPrediction,
useActualCurrentStartDateSelector,
} from '../../components/context/PredictionProvider'
import { useSelector } from '../../redux/useSelector'

function checkForVerifiedDay(cardValues) {
if (_.has(cardValues, 'periodDay')) {
Expand Down
2 changes: 1 addition & 1 deletion packages/components/src/components/common/DayBadge.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ import styled from 'styled-components/native'
import { TextWithoutTranslation, Text } from './Text'
import _ from 'lodash'
import moment from 'moment'
import { useSelector } from 'react-redux'
import * as selectors from '../../redux/selectors'
import {
useTodayPrediction,
useActualCurrentStartDateSelector,
} from '../../components/context/PredictionProvider'
import { useSelector } from '../../redux/useSelector'

function checkForVerifiedDay(cardValues) {
if (_.has(cardValues, 'periodDay')) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react'
import styled from 'styled-components/native'
import { useSelector } from '../../hooks/useSelector'
import { useSelector } from '../../redux/useSelector'
import * as selectors from '../../redux/selectors'
import * as actions from '../../redux/actions/index'
import { useDispatch } from 'react-redux'
Expand Down
2 changes: 2 additions & 0 deletions packages/components/src/components/common/TextInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export const TextInput = ({
errorContent = 'No message',
placeholderColor = '#28b9cb',
infoAccessibilityLabel = '',
editable = true,
}) => {
const [isVisible, setIsVisible] = React.useState(false)
return (
Expand All @@ -47,6 +48,7 @@ export const TextInput = ({
style={{ color: '#555', ...inputStyle }}
secureTextEntry={secureTextEntry}
value={value}
editable={editable}
/>
{isValid && !hasError && (
<Icon
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from 'react'
import Tts from 'react-native-tts'
import _ from 'lodash'
import { translate } from '../../i18n'
import { useSelector } from '../../hooks/useSelector'
import { useSelector } from '../../redux/useSelector'
import * as selectors from '../../redux/selectors'

interface Props {
Expand Down
4 changes: 2 additions & 2 deletions packages/components/src/components/context/LocaleContext.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import React from 'react'
import { useSelector } from '../../hooks/useSelector'
import { useSelector } from '../../redux/useSelector'
import { currentLocale, configureI18n } from '../../i18n'

export function LocaleProvider({ children }) {
const locale = useSelector(state => state.app.locale)
const locale = useSelector((state) => state.app.locale)
const [syncLocale, setSyncLocale] = React.useState(currentLocale())

React.useLayoutEffect(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import moment, { Moment } from 'moment'
import _ from 'lodash'
import { PredictionState, PredictionEngine } from '../../prediction'

import { useSelector } from '../../hooks/useSelector'
import { useSelector } from '../../redux/useSelector'
import { useDispatch } from 'react-redux'
import * as actions from '../../redux/actions'

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react'
import { ThemeContext, ThemeProvider as StyledThemeProvider } from 'styled-components'
import { useSelector } from '../../hooks/useSelector'
import { useSelector } from '../../redux/useSelector'
import * as selectors from '../../redux/selectors'
import { themes } from '@oky/core'

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import styled from 'styled-components/native'
import { useTheme } from '../context/ThemeContext'
import { useTodayPrediction } from '../context/PredictionProvider'
import { assets } from '../../assets'
import { ThemeName } from '@oky/core'
import { ThemeName, defaultTheme } from '@oky/core'

function getBackgroundImage(theme: ThemeName, onPeriod: boolean) {
const background = assets.backgrounds[theme]
Expand All @@ -25,6 +25,13 @@ export function BackgroundTheme({ theme = null, ...props }) {
return <Background source={backgroundImage} {...props} />
}

export function DefaultBackgroundTheme({ ...props }) {
// TODO_ALEX getAsset() safely
const backgroundImage = assets.backgrounds[defaultTheme].default

return <Background source={backgroundImage} {...props} />
}

const Background = styled.ImageBackground`
width: 100%;
height: 100%;
Expand Down
2 changes: 1 addition & 1 deletion packages/components/src/config/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ export const PREDICTION_ENDPOINT = env.PREDICTION_ENDPOINT
export const WEBSITE_URL = env.WEBSITE_URL

// Development purposes only
export const FAST_SIGN_UP = false
export const FAST_SIGN_UP = true
47 changes: 25 additions & 22 deletions packages/components/src/config/speech.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,28 +80,31 @@ export const profileScreenSpeech = ({
dateOfBirth,
selectedAvatar,
theme,
}) => [
translate('arrow_button'),
translate('profile'),
translate('name'),
currentUser.name,
translate('age'),
translate(dateOfBirth.format('MMM')) + ' ' + dateOfBirth.format('YYYY'),
translate('gender'),
translate(currentUser.gender),
translate('green_btn_with_two_arrows'),
translate('location'),
translate(currentUser.location),
translate('green_btn_with_two_arrows'),
translate('cycle_length'),
todayInfo.cycleLength.toString() + translate('days'),
translate('period_length'),
todayInfo?.periodLength?.toString() + translate('days'),
// translate(`selected_avatar`),
translate(selectedAvatar),
// translate('selected_theme'),
translate(theme),
]
}) => {
if (!currentUser) return [translate('arrow_button'), translate('profile')]
return [
translate('arrow_button'),
translate('profile'),
translate('name'),
currentUser.name,
translate('age'),
translate(dateOfBirth.format('MMM')) + ' ' + dateOfBirth.format('YYYY'),
translate('gender'),
translate(currentUser.gender),
translate('green_btn_with_two_arrows'),
translate('location'),
translate(currentUser.location),
translate('green_btn_with_two_arrows'),
translate('cycle_length'),
todayInfo.cycleLength.toString() + translate('days'),
translate('period_length'),
todayInfo?.periodLength?.toString() + translate('days'),
// translate(`selected_avatar`),
translate(selectedAvatar),
// translate('selected_theme'),
translate(theme),
]
}

export const settingsScreenText = ({ hasTtsActive }) => [
translate('settings'),
Expand Down
7 changes: 0 additions & 7 deletions packages/components/src/hooks/useSelector.ts

This file was deleted.

2 changes: 1 addition & 1 deletion packages/components/src/hooks/useTextToSpeechHook.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react'
import { speakArray, clearTTSQueue } from '../services/textToSpeech'
import { useSelector } from './useSelector'
import { useSelector } from '../redux/useSelector'
import * as selectors from '../redux/selectors'

export function useTextToSpeechHook({ navigation, text }) {
Expand Down
7 changes: 7 additions & 0 deletions packages/components/src/navigators/AppNavigator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ import { FindHelpScreen } from '../screens/FindHelpScreen'
import { PasswordRequestScreen } from '../screens/PasswordRequestScreen'
import { VideoScreen } from '../screens/VideoScreen'
import { VideosScreen } from '../screens/VideosScreen'
import { StoreSwitchSplash } from '../redux/StoreSwitchSplash'

const StoreSwitchStack = createStackNavigator(
{ StoreSwitchSplash },
{ headerMode: 'none', initialRouteName: 'StoreSwitchSplash' },
)

const TutorialFirstStack = createStackNavigator(
{ TutorialFirstScreen },
Expand Down Expand Up @@ -131,6 +137,7 @@ const MainStack = createBottomTabNavigator(

const AppNavigator = createStackNavigator(
{
StoreSwitchStack,
SplashScreen,
OnboardingScreen,
PasswordRequestScreen,
Expand Down
1 change: 0 additions & 1 deletion packages/components/src/prediction/PredictionState.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import moment, { Moment } from 'moment'
import { AppState } from '../redux/reducers/appReducer'
import CircularBuffer from 'circular-buffer'

interface CurrentCycle {
Expand Down
Loading