Skip to content

Commit

Permalink
fix autosubscribing across sessions (#1347)
Browse files Browse the repository at this point in the history
* fix autosubscribing across sessions

* remove debug code

* remove envs from other branch

* remove prop

* tests
  • Loading branch information
JacobJaffe authored Aug 7, 2020
1 parent 1a6cbaa commit 78cf06e
Show file tree
Hide file tree
Showing 17 changed files with 146 additions and 212 deletions.
2 changes: 1 addition & 1 deletion app/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@
"notifications_off_subheader": "You will not receive notifications about possible exposures nor when new Health Departments are added in your area",
"select_authority_button": "Add Health Department",
"select_authority_header": "No local Health Department Selected",
"select_authority_subheader": "Allow PathCheck to add your local Health Department or select one yourself to receive info about COVID-19 in your area"
"select_authority_subheader": "Select your local Health Department to receive info about COVID-19 in your area"
}
},
"import": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,10 @@ const getHealthcareAuthoritiesAction = (
dispatch(
toggleSelectedHealthcareAuthorityAction(
{ authority: localHealthAuthority, overrideValue: true },
{ triggerIntersect: false },
{
triggerIntersect: false,
autoSubscribed: !!autoSubscriptionLocation,
},
),
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { createAction } from '@reduxjs/toolkit';

const TOGGLE_AUTO_SUBSCRIPTION_BANNER = 'TOGGLE_AUTO_SUBSCRIPTION_BANNER';

/**
* Enables / disables the auto-subscription banner from being shown
*/
const toggleAutoSubscriptionBannerAction = createAction<{
overrideValue: boolean;
}>(TOGGLE_AUTO_SUBSCRIPTION_BANNER);

export default toggleAutoSubscriptionBannerAction;

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,21 @@ type Payload = {
};

type Meta = {
triggerIntersect: boolean;
triggerIntersect?: boolean; // indicates that this action should trigger a recomputation of possible exposure notifications
autoSubscribed?: boolean; // indicates that this was triggered via geofencing auto subscription
};

const TOGGLE_SELECTED_HEALTHCARE_AUTHORITY =
'TOGGLE_SELECTED_HEALTHCARE_AUTHORITY';

const toggleSelectedHealthcareAuthorityAction = createAction(
TOGGLE_SELECTED_HEALTHCARE_AUTHORITY,
({ authority, overrideValue }: Payload, { triggerIntersect }: Meta) => ({
(
{ authority, overrideValue }: Payload,
{ triggerIntersect, autoSubscribed }: Meta,
) => ({
payload: { authority, overrideValue },
meta: { triggerIntersect },
meta: { triggerIntersect, autoSubscribed },
}),
);

Expand Down
2 changes: 1 addition & 1 deletion app/store/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const enhancers = composeWithDevTools(
),
);

export const STORE_VERSION = 1;
export const STORE_VERSION = 2;
const persistConfig = {
key: 'root',
storage: AsyncStorage,
Expand Down
15 changes: 15 additions & 0 deletions app/store/migrations/migrations.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,21 @@ const migrations = {
}
return prevState;
},
// Migration 2: Introduce auto-subscription
2: (prevState) => {
if (prevState && prevState.healthcareAuthorities) {
prevState.healthcareAuthorities.autoSubscription = {
bannerDismissed: false,
selectedAuthority: null,
// only auto-subscribe if user has no HAs.
active:
!prevState.healthcareAuthorities.availableCustomAuthorities ||
prevState.healthcareAuthorities.availableCustomAuthorities.length ===
0,
};
}
return prevState;
},
};

export default migrations;
32 changes: 25 additions & 7 deletions app/store/reducers/healthcareAuthoritiesReducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,35 @@ import {
getHealthcareAuthorities_success,
} from '../actions/healthcareAuthorities/getHealthcareAuthoritiesAction';
import toggleSelectedHealthcareAuthorityAction from '../actions/healthcareAuthorities/toggleSelectedHealthcareAuthorityAction';
import toggleHealthcareAuthorityAutoSubscription from '../actions/healthcareAuthorities/toggleHealthcareAuthorityAutoSubscription';
import toggleAutoSubscriptionBannerAction from '../actions/healthcareAuthorities/toggleAutoSubscriptionBannerAction';

type HealthCareReducerState = {
// Because we control this list to be super small and have type safety, we use the full models
// rather than a normalized map / id list paradigm.
availableAuthorities: HealthcareAuthority[];
availableCustomAuthorities: HealthcareAuthority[];
selectedAuthorities: HealthcareAuthority[];
autoSubscriptionEnabled: boolean;
request: ApiRequest;
autoSubscription: {
active: boolean; // controls firing. We set to false after any toggle so that auto-subscribe happens max of once, and before manual.
bannerDismissed: boolean; // independently show banner until dismissed
selectedAuthority: HealthcareAuthority | null;
};
};

const initialState: HealthCareReducerState = {
availableAuthorities: [],
availableCustomAuthorities: [], // For testing, from a custom uploaded YAML
selectedAuthorities: [],
autoSubscriptionEnabled: true,
request: {
status: ApiStatus.INITIAL,
errorMessage: null,
},
autoSubscription: {
active: true,
bannerDismissed: false,
selectedAuthority: null,
},
};

// The 'request' property of this reducer is helpful metadata for showing loading / error cases
Expand Down Expand Up @@ -71,21 +79,31 @@ const healthcareAuthoritiesReducer = createReducer(initialState, (builder) =>
})
.addCase(
toggleSelectedHealthcareAuthorityAction,
(state, { payload: { authority, overrideValue } }) => {
(
state,
{ payload: { authority, overrideValue }, meta: { autoSubscribed } },
) => {
// always remove
state.selectedAuthorities = state.selectedAuthorities.filter(
({ internal_id }) => internal_id !== authority.internal_id,
);
// add if needed
if (overrideValue) {
state.selectedAuthorities.push(authority);
state.autoSubscription.active = false; // after we subscribe, for any reason, prevent auto-subscribing
}

// Display banner that HA was auto-subscribed to
if (autoSubscribed) {
state.autoSubscription.bannerDismissed = false;
state.autoSubscription.selectedAuthority = authority;
}
},
)
.addCase(
toggleHealthcareAuthorityAutoSubscription,
(state, { payload: { autoSubscriptionEnabled } }) => {
state.autoSubscriptionEnabled = autoSubscriptionEnabled;
toggleAutoSubscriptionBannerAction,
(state, { payload: { overrideValue } }) => {
state.autoSubscription.bannerDismissed = !overrideValue;
},
),
);
Expand Down
5 changes: 0 additions & 5 deletions app/store/selectors/isAutoSubscriptionEnabledSelector.ts

This file was deleted.

33 changes: 28 additions & 5 deletions app/views/Main.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,16 @@ import { AllServicesOnScreen } from './main/AllServicesOn';
import {
TracingOffScreen,
NotificationsOffScreen,
// SelectAuthorityScreen,
SelectAuthorityScreen,
} from './main/ServiceOffScreens';
import PermissionsContext from '../gps/PermissionsContext';
import { PermissionStatus } from '../permissionStatus';

import { useSelector } from 'react-redux';
import { useSelector, useDispatch } from 'react-redux';
import selectedHealthcareAuthoritiesSelector from '../store/selectors/selectedHealthcareAuthoritiesSelector';
import { useStatusBarEffect } from '../navigation';
import getHealthcareAuthoritiesAction from '../store/actions/healthcareAuthorities/getHealthcareAuthoritiesAction';
import Geolocation from '@react-native-community/geolocation';

export const Main = () => {
useStatusBarEffect('light-content');
Expand Down Expand Up @@ -47,14 +49,35 @@ export const Main = () => {
};
}, [navigation, updateStateInfo]);

const dispatch = useDispatch();
const { autoSubscription } = useSelector(
(state) => state.healthcareAuthorities,
);

const autoSubscribe = useCallback(async () => {
if (autoSubscription.active) {
Geolocation.getCurrentPosition(({ coords }) => {
dispatch(
getHealthcareAuthoritiesAction({ autoSubscriptionLocation: coords }),
);
});
}
}, [autoSubscription, dispatch]);

useEffect(() => {
autoSubscribe();
}, [autoSubscribe]);

if (!canTrack) {
return <TracingOffScreen />;
} else if (notification.status === PermissionStatus.DENIED) {
return <NotificationsOffScreen />;
} else if (selectedAuthorities.length === 0) {
// TODO: enable this for testing versions of app
// return <SelectAuthorityScreen />;
return <AllServicesOnScreen navigation={navigation} noHaAvailable />;
if (autoSubscription.active) {
return <AllServicesOnScreen navigation={navigation} />;
} else {
return <SelectAuthorityScreen />;
}
} else {
return <AllServicesOnScreen navigation={navigation} />;
}
Expand Down
46 changes: 0 additions & 46 deletions app/views/Partners/PartnersOverview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,6 @@ import { Typography } from '../../components/Typography';
import { Images, Icons } from '../../assets';
import { Colors } from '../../styles';

import { useSelector, useDispatch } from 'react-redux';
import toggleHealthcareAuthorityAutoSubscription from '../../store/actions/healthcareAuthorities/toggleHealthcareAuthorityAutoSubscription';
import isAutoSubscriptionEnabledSelector from '../../store/selectors/isAutoSubscriptionEnabledSelector';
import { Switch } from 'react-native-gesture-handler';

// For fixing image width issues
const win = Dimensions.get('window');

Expand Down Expand Up @@ -71,20 +66,8 @@ const PartnersIllustration = (): JSX.Element => {

const PartnersScreen = ({ navigation }: PartnersScreenProps): JSX.Element => {
const { t } = useTranslation();
const dispatch = useDispatch();
const navigateToViewHAs = () => navigation.navigate('PartnersEdit');

const autoSubscriptionEnabled = useSelector(
isAutoSubscriptionEnabledSelector,
);
const onToggleAutoSubscription = (value: boolean) => {
dispatch(
toggleHealthcareAuthorityAutoSubscription({
autoSubscriptionEnabled: value,
}),
);
};

return (
<NavigationBarWrapper
title={t('authorities.title')}
Expand Down Expand Up @@ -130,26 +113,6 @@ const PartnersScreen = ({ navigation }: PartnersScreenProps): JSX.Element => {
<View style={styles.divider} />
<View style={{ height: 24 }} />
</ScrollView>
{__DEV__ && (
<View style={styles.bottomSheet}>
<Typography
style={{
// Prevent from forcing overflow on parent
flex: 1,
}}>
{t('authorities.automatically_follow')}
</Typography>
<View style={{ width: 16 }} />
<Switch
trackColor={{
true: Colors.switchEnabled,
false: Colors.switchDisabled,
}}
value={autoSubscriptionEnabled}
onValueChange={onToggleAutoSubscription}
/>
</View>
)}
</NavigationBarWrapper>
);
};
Expand All @@ -160,15 +123,6 @@ const styles = StyleSheet.create({
backgroundColor: Colors.primaryBackground,
flex: 1,
},
bottomSheet: {
backgroundColor: Colors.bottomSheetBackground,
padding: 24,
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
borderTopWidth: StyleSheet.hairlineWidth,
borderTopColor: Colors.formInputBorder,
},
divider: {
height: 1,
backgroundColor: Colors.formInputBorder,
Expand Down
Loading

0 comments on commit 78cf06e

Please sign in to comment.