diff --git a/src/Screens/VersionCheck/index.tsx b/src/Screens/VersionCheck/index.tsx new file mode 100644 index 00000000..5ae188b2 --- /dev/null +++ b/src/Screens/VersionCheck/index.tsx @@ -0,0 +1,46 @@ +import React from 'react'; +import RN from 'react-native'; +import * as RD from '@devexperts/remote-data-ts'; + +import { StackScreenProps } from '@react-navigation/stack'; +import { StackRoutes } from '..'; + +import * as redux from 'redux'; +import { useDispatch, useSelector } from 'react-redux'; +import { selectClientVersions } from 'src/state/reducers/minimumVersion'; + +import * as actions from '../../state/actions'; + +import colors from '../components/colors'; + +export type VersionCheckRoute = { + VersionCheck: {}; +}; + +type Props = StackScreenProps; + +const VersionCheck = ({ navigation }: Props) => { + const dispatch = useDispatch>(); + React.useEffect(() => { + dispatch({ type: 'minimumVersion/get/start', payload: undefined }); + }, []); + + const versionState = useSelector(selectClientVersions); + + React.useEffect(() => { + if (RD.isSuccess(versionState)) { + navigation.replace('Splash', {}); + } + }, [versionState]); + + return ; +}; + +const styles = RN.StyleSheet.create({ + background: { + backgroundColor: colors.purplePale, + flex: 1, + }, +}); + +export default VersionCheck; diff --git a/src/Screens/index.tsx b/src/Screens/index.tsx index ac3acd25..b623aa25 100644 --- a/src/Screens/index.tsx +++ b/src/Screens/index.tsx @@ -28,8 +28,10 @@ import DeleteAccount, { import PasswordChange, { PasswordChangeRoute } from './Main/Settings/Password'; import EmailChange, { EmailChangeRoute } from './Main/Settings/Email/Email'; import UserReport, { UserReportRoute } from './Main/UserReport'; +import { VersionCheckRoute } from './VersionCheck'; export type StackRoutes = SplashRoute & + VersionCheckRoute & WelcomeRoute & MentorListRoute & SignRoute & @@ -54,7 +56,7 @@ const Stack = reactNavigationStack.createStackNavigator(); export default () => ( diff --git a/src/api/minimumVersion.ts b/src/api/minimumVersion.ts new file mode 100644 index 00000000..43997f9b --- /dev/null +++ b/src/api/minimumVersion.ts @@ -0,0 +1,24 @@ +import * as t from 'io-ts'; +import * as TE from 'fp-ts/lib/TaskEither'; + +import * as http from '../lib/http'; + +import * as config from './config'; + +const clientVersions = t.strict({ + ylitse_ios: t.string, + ylitse_android: t.string, +}); + +const versionsResponse = t.strict({ + resources: clientVersions, +}); + +export type ClientVersions = t.TypeOf; + +export const fetchVersions: () => TE.TaskEither = () => + http.validateResponse( + http.get(`${config.baseUrl}/version/clients`), + versionsResponse, + response => response.resources, + ); diff --git a/src/state/actions/regular.ts b/src/state/actions/regular.ts index b16deb50..3fab6bce 100644 --- a/src/state/actions/regular.ts +++ b/src/state/actions/regular.ts @@ -10,6 +10,7 @@ import * as messageApi from '../../api/messages'; import * as statApi from '../../api/stat'; import * as userReportApi from '../../api/userReport'; import * as feedbackApi from '../../api/feedback'; +import * as minimumVersionApi from '../../api/minimumVersion'; import * as messages from '../reducers/messages'; import * as updateMentorData from '../reducers/updateMentorData'; @@ -126,6 +127,9 @@ type RegularActions = { 'feedback/sendAnswer/start': feedbackApi.Answer; 'feedback/sendAnswer/end': Result>; 'feedback/reset/': undefined; + + 'minimumVersion/get/start': undefined; + 'minimumVersion/get/end': Result; }; // TODO name plz. diff --git a/src/state/reducers/index.ts b/src/state/reducers/index.ts index 34ec2345..c765637e 100644 --- a/src/state/reducers/index.ts +++ b/src/state/reducers/index.ts @@ -26,6 +26,7 @@ import * as userReport from './userReport'; import * as updateMentorData from './updateMentorData'; import * as questions from './questions'; import * as filterMentors from './filterMentors'; +import * as minimumVersion from './minimumVersion'; import * as actions from '../actions'; @@ -72,6 +73,7 @@ export const rootReducer: automaton.Reducer = markMessageSeen: markSeen.reducer, feedbackQuestions: questions.reducer, filterMentors: filterMentors.filterMentorsReducer, + minimumVersion: minimumVersion.reducer, }), ); @@ -96,4 +98,5 @@ export const initialState: AppState = { markMessageSeen: {}, feedbackQuestions: questions.initialState, filterMentors: filterMentors.initialState, + minimumVersion: minimumVersion.initialState, }; diff --git a/src/state/reducers/minimumVersion.ts b/src/state/reducers/minimumVersion.ts new file mode 100644 index 00000000..5a52cc38 --- /dev/null +++ b/src/state/reducers/minimumVersion.ts @@ -0,0 +1,49 @@ +import { Reducer } from 'redux-automaton'; +import * as RD from '@devexperts/remote-data-ts'; +import * as automaton from 'redux-automaton'; +import * as actions from '../actions'; +import * as T from 'fp-ts/lib/Task'; + +import * as minimumVersionApi from '../../api/minimumVersion'; +import { cmd } from '../middleware'; + +import { Action } from '../actions'; +import { AppState } from '../types'; + +import { pipe } from 'fp-ts/lib/function'; + +export const initialState = RD.initial; + +export const reducer: Reducer = ( + state = initialState, + action, +) => { + switch (action.type) { + case 'minimumVersion/get/start': { + if (RD.isPending(state)) { + return state; + } + + return automaton.loop( + RD.pending, + cmd( + pipe( + minimumVersionApi.fetchVersions(), + T.map(actions.make('minimumVersion/get/end')), + ), + ), + ); + } + + case 'minimumVersion/get/end': { + return pipe(action.payload, RD.fromEither); + } + + default: { + return state; + } + } +}; + +export const selectClientVersions = ({ minimumVersion }: AppState) => + minimumVersion; diff --git a/src/state/types.ts b/src/state/types.ts index 105b26a5..b60b1aa4 100644 --- a/src/state/types.ts +++ b/src/state/types.ts @@ -7,6 +7,7 @@ import * as buddyApi from '../api/buddies'; import * as mentorsApi from '../api/mentors'; import * as messageApi from '../api/messages'; import * as feedbackApi from '../api/feedback'; +import * as minimumVersionApi from '../api/minimumVersion'; import { PollingParams } from './reducers/messages'; import { UpdateKey } from './reducers/updateMentorData'; @@ -75,4 +76,5 @@ export type AppState = { sendDeviceToken: RemoteAction; }; feedbackQuestions: RemoteData>; + minimumVersion: RemoteData; };