Skip to content

Commit 5a569b9

Browse files
committed
session [nfc]: Track when register-push-token requests are in progress
No need for a migration; session state isn't persisted.
1 parent 1c78400 commit 5a569b9

File tree

5 files changed

+117
-5
lines changed

5 files changed

+117
-5
lines changed

src/actionConstants.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ export const DISMISS_SERVER_COMPAT_NOTICE: 'DISMISS_SERVER_COMPAT_NOTICE' =
6161
'DISMISS_SERVER_COMPAT_NOTICE';
6262

6363
export const GOT_PUSH_TOKEN: 'GOT_PUSH_TOKEN' = 'GOT_PUSH_TOKEN';
64+
export const REGISTER_PUSH_TOKEN_START: 'REGISTER_PUSH_TOKEN_START' = 'REGISTER_PUSH_TOKEN_START';
65+
export const REGISTER_PUSH_TOKEN_END: 'REGISTER_PUSH_TOKEN_END' = 'REGISTER_PUSH_TOKEN_END';
6466
export const ACK_PUSH_TOKEN: 'ACK_PUSH_TOKEN' = 'ACK_PUSH_TOKEN';
6567
export const UNACK_PUSH_TOKEN: 'UNACK_PUSH_TOKEN' = 'UNACK_PUSH_TOKEN';
6668

src/actionTypes.js

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ import {
5858
EVENT_SUBSCRIPTION,
5959
EVENT,
6060
DISMISS_SERVER_COMPAT_NOTICE,
61+
REGISTER_PUSH_TOKEN_START,
62+
REGISTER_PUSH_TOKEN_END,
6163
} from './actionConstants';
6264

6365
import type { UserMessageFlag } from './api/modelTypes';
@@ -186,6 +188,18 @@ type UnackPushTokenAction = $ReadOnly<{|
186188
identity: Identity,
187189
|}>;
188190

191+
/** We've started a request to register our device token. */
192+
type RegisterPushTokenStartAction = $ReadOnly<{|
193+
type: typeof REGISTER_PUSH_TOKEN_START,
194+
identity: Identity,
195+
|}>;
196+
197+
/** A request to register our device token has ended (success or failure). */
198+
type RegisterPushTokenEndAction = $ReadOnly<{|
199+
type: typeof REGISTER_PUSH_TOKEN_END,
200+
identity: Identity,
201+
|}>;
202+
189203
/** The server acknowledged our device token. */
190204
type AckPushTokenAction = $ReadOnly<{|
191205
type: typeof ACK_PUSH_TOKEN,
@@ -671,9 +685,9 @@ export type AllAccountsAction =
671685
| LoginSuccessAction
672686
| LogoutAction
673687
| DismissServerPushSetupNoticeAction
674-
// These two are about a specific account… but not just the active one,
688+
// These four are about a specific account… but not just the active one,
675689
// and they encode which one they mean.
676-
| AckPushTokenAction | UnackPushTokenAction
690+
| RegisterPushTokenEndAction | RegisterPushTokenStartAction | AckPushTokenAction | UnackPushTokenAction
677691
;
678692

679693
/** Plain actions not affecting any per-account state. */
@@ -794,6 +808,8 @@ export function isPerAccountApplicableAction(action: Action): boolean {
794808
case ACCOUNT_REMOVE:
795809
case LOGIN_SUCCESS:
796810
case LOGOUT:
811+
case REGISTER_PUSH_TOKEN_START:
812+
case REGISTER_PUSH_TOKEN_END:
797813
case ACK_PUSH_TOKEN:
798814
case UNACK_PUSH_TOKEN:
799815
(action: AllAccountsAction);

src/notification/notifTokens.js

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,13 @@
66
import { NativeModules, Platform } from 'react-native';
77
import PushNotificationIOS from '@react-native-community/push-notification-ios';
88

9-
import { GOT_PUSH_TOKEN, ACK_PUSH_TOKEN, UNACK_PUSH_TOKEN } from '../actionConstants';
9+
import {
10+
GOT_PUSH_TOKEN,
11+
ACK_PUSH_TOKEN,
12+
REGISTER_PUSH_TOKEN_START,
13+
UNACK_PUSH_TOKEN,
14+
REGISTER_PUSH_TOKEN_END,
15+
} from '../actionConstants';
1016
import type {
1117
Account,
1218
Identity,
@@ -119,6 +125,16 @@ const unackPushToken = (identity: Identity): AllAccountsAction => ({
119125
identity,
120126
});
121127

128+
const registerPushTokenStart = (identity: Identity): AllAccountsAction => ({
129+
type: REGISTER_PUSH_TOKEN_START,
130+
identity,
131+
});
132+
133+
const registerPushTokenEnd = (identity: Identity): AllAccountsAction => ({
134+
type: REGISTER_PUSH_TOKEN_END,
135+
identity,
136+
});
137+
122138
const ackPushToken = (pushToken: string, identity: Identity): AllAccountsAction => ({
123139
type: ACK_PUSH_TOKEN,
124140
identity,
@@ -148,8 +164,14 @@ const sendPushToken =
148164
return;
149165
}
150166
const auth = authOfAccount(account);
151-
await api.savePushToken(auth, Platform.OS, pushToken);
152-
dispatch(ackPushToken(pushToken, identityOfAccount(account)));
167+
const identity = identityOfAccount(account);
168+
dispatch(registerPushTokenStart(identity));
169+
try {
170+
await api.savePushToken(auth, Platform.OS, pushToken);
171+
dispatch(ackPushToken(pushToken, identity));
172+
} finally {
173+
dispatch(registerPushTokenEnd(identity));
174+
}
153175
};
154176

155177
/** Tell this account's server about our device token, if needed. */

src/session/__tests__/sessionReducer-test.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,12 @@ import {
1010
TOGGLE_OUTBOX_SENDING,
1111
DISMISS_SERVER_COMPAT_NOTICE,
1212
REGISTER_START,
13+
REGISTER_PUSH_TOKEN_START,
14+
REGISTER_PUSH_TOKEN_END,
1315
} from '../../actionConstants';
1416
import sessionReducer, { initialPerAccountSessionState } from '../sessionReducer';
1517
import * as eg from '../../__tests__/lib/exampleData';
18+
import { identityOfAccount } from '../../account/accountMisc';
1619

1720
describe('sessionReducer', () => {
1821
const baseState = eg.baseReduxState.session;
@@ -94,6 +97,35 @@ describe('sessionReducer', () => {
9497
});
9598
});
9699

100+
test('REGISTER_PUSH_TOKEN_START / REGISTER_PUSH_TOKEN_END increment/decrement counter', () => {
101+
const run = (state, type, account) =>
102+
sessionReducer(
103+
state,
104+
type === 'start'
105+
? { type: REGISTER_PUSH_TOKEN_START, identity: identityOfAccount(account) }
106+
: { type: REGISTER_PUSH_TOKEN_END, identity: identityOfAccount(account) },
107+
eg.plusReduxState,
108+
);
109+
110+
const state1 = run(baseState, 'start', eg.selfAccount);
111+
expect(state1.registerPushTokenRequestsInProgress).toEqual(1);
112+
113+
const state2 = run(state1, 'start', eg.selfAccount);
114+
expect(state2.registerPushTokenRequestsInProgress).toEqual(2);
115+
116+
const state3 = run(state2, 'end', eg.selfAccount);
117+
expect(state3.registerPushTokenRequestsInProgress).toEqual(1);
118+
119+
const state4 = run(state3, 'end', eg.selfAccount);
120+
expect(state4.registerPushTokenRequestsInProgress).toEqual(0);
121+
122+
const state5 = run(state4, 'start', eg.makeAccount());
123+
expect(state5).toBe(state4);
124+
125+
const state7 = run(state5, 'end', eg.makeAccount());
126+
expect(state7).toBe(state5);
127+
});
128+
97129
test('TOGGLE_OUTBOX_SENDING', () => {
98130
const state = deepFreeze({ ...baseState, outboxSending: false });
99131
expect(

src/session/sessionReducer.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
/* @flow strict-local */
22
import type { GlobalState } from '../reduxTypes';
33
import type { Orientation, Action } from '../types';
4+
import { keyOfIdentity } from '../account/accountMisc';
5+
import { getIdentity, tryGetActiveAccountState } from '../account/accountsSelectors';
46
import {
57
REHYDRATE,
68
DEAD_QUEUE,
@@ -13,6 +15,8 @@ import {
1315
TOGGLE_OUTBOX_SENDING,
1416
GOT_PUSH_TOKEN,
1517
DISMISS_SERVER_COMPAT_NOTICE,
18+
REGISTER_PUSH_TOKEN_START,
19+
REGISTER_PUSH_TOKEN_END,
1620
} from '../actionConstants';
1721

1822
/**
@@ -53,6 +57,11 @@ export type PerAccountSessionState = $ReadOnly<{
5357
*/
5458
hasDismissedServerCompatNotice: boolean,
5559

60+
/**
61+
* How many `api.savePushToken` requests are in progress for this account.
62+
*/
63+
registerPushTokenRequestsInProgress: number,
64+
5665
...
5766
}>;
5867

@@ -128,6 +137,7 @@ export const initialPerAccountSessionState: $Exact<PerAccountSessionState> = {
128137
loading: false,
129138
outboxSending: false,
130139
hasDismissedServerCompatNotice: false,
140+
registerPushTokenRequestsInProgress: 0,
131141
};
132142

133143
const initialState: SessionState = {
@@ -205,6 +215,36 @@ export default (
205215
pushToken: action.pushToken,
206216
};
207217

218+
case REGISTER_PUSH_TOKEN_START: {
219+
// TODO(#5006): Do for any account, not just the active one
220+
const activeAccountState = tryGetActiveAccountState(globalState);
221+
if (
222+
!activeAccountState
223+
|| keyOfIdentity(action.identity) !== keyOfIdentity(getIdentity(activeAccountState))
224+
) {
225+
return state;
226+
}
227+
return {
228+
...state,
229+
registerPushTokenRequestsInProgress: state.registerPushTokenRequestsInProgress + 1,
230+
};
231+
}
232+
233+
case REGISTER_PUSH_TOKEN_END: {
234+
// TODO(#5006): Do for any account, not just the active one
235+
const activeAccountState = tryGetActiveAccountState(globalState);
236+
if (
237+
!activeAccountState
238+
|| keyOfIdentity(action.identity) !== keyOfIdentity(getIdentity(activeAccountState))
239+
) {
240+
return state;
241+
}
242+
return {
243+
...state,
244+
registerPushTokenRequestsInProgress: state.registerPushTokenRequestsInProgress - 1,
245+
};
246+
}
247+
208248
case TOGGLE_OUTBOX_SENDING:
209249
return { ...state, outboxSending: action.sending };
210250

0 commit comments

Comments
 (0)