Skip to content

Commit 2f83953

Browse files
committed
presence: Give PresenceState a better data structure, and room for more
For #5669, we'll want to add a bit more information here alongside the per-user data. Insert an object sitting above the per-user map, to be a place we can add those; and while we're here, make that per-user map an Immutable.Map, instead of an object-as-map.
1 parent a7da011 commit 2f83953

File tree

3 files changed

+32
-29
lines changed

3 files changed

+32
-29
lines changed

src/presence/presenceModel.js

Lines changed: 29 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
/* @flow strict-local */
2+
import Immutable from 'immutable';
23
import differenceInSeconds from 'date-fns/differenceInSeconds';
34
import differenceInDays from 'date-fns/differenceInDays';
45
import formatDistanceToNow from 'date-fns/formatDistanceToNow';
@@ -24,7 +25,6 @@ import {
2425
REGISTER_COMPLETE,
2526
RESET_ACCOUNT_DATA,
2627
} from '../actionConstants';
27-
import { NULL_OBJECT } from '../nullObjects';
2828

2929
//
3030
//
@@ -34,7 +34,7 @@ import { NULL_OBJECT } from '../nullObjects';
3434
export const getPresence = (state: PerAccountState): PresenceState => state.presence;
3535

3636
export function getUserPresenceByEmail(state: PresenceState, email: string): UserPresence | void {
37-
return state[email];
37+
return state.byEmail.get(email);
3838
}
3939

4040
//
@@ -196,7 +196,9 @@ export const getPresenceStatusForUserId = (
196196
// Reducer.
197197
//
198198

199-
const initialState: PresenceState = NULL_OBJECT;
199+
const initialState: PresenceState = {
200+
byEmail: Immutable.Map(),
201+
};
200202

201203
export function reducer(
202204
state: PresenceState = initialState, // eslint-disable-line default-param-last
@@ -206,22 +208,23 @@ export function reducer(
206208
case RESET_ACCOUNT_DATA:
207209
return initialState;
208210

209-
case REGISTER_COMPLETE:
210-
return (
211-
action.data.presences
212-
// TODO(#5102): Delete fallback once we enforce any threshold for
213-
// ancient servers we refuse to connect to. It was added in
214-
// #2878 (2018-11-16), but it wasn't clear even then, it seems,
215-
// whether any servers actually omit the data. The API doc
216-
// doesn't mention any servers that omit it, and our Flow types
217-
// mark it required.
218-
|| initialState
219-
);
211+
case REGISTER_COMPLETE: {
212+
// TODO(#5102): Delete fallback once we enforce any threshold for
213+
// ancient servers we refuse to connect to. It was added in
214+
// #2878 (2018-11-16), but it wasn't clear even then, it seems,
215+
// whether any servers actually omit the data. The API doc
216+
// doesn't mention any servers that omit it, and our Flow types
217+
// mark it required.
218+
const data = action.data.presences ?? {};
219+
return {
220+
byEmail: Immutable.Map(data),
221+
};
222+
}
220223

221224
case PRESENCE_RESPONSE:
222225
return {
223226
...state,
224-
...action.presence,
227+
byEmail: state.byEmail.merge(action.presence),
225228
};
226229

227230
case EVENT_PRESENCE: {
@@ -233,25 +236,23 @@ export function reducer(
233236
return state;
234237
}
235238

236-
const oldUserPresence = getUserPresenceByEmail(state, action.email);
237239
return {
238240
...state,
239-
// Flow bug (unresolved):
240-
// https://github.com/facebook/flow/issues/8276
241-
// $FlowIssue[cannot-spread-indexer] #8276
242-
[action.email]: {
243-
...oldUserPresence,
244-
...action.presence,
245-
// Flow bug (unresolved):
246-
// https://github.com/facebook/flow/issues/8276
247-
// $FlowIssue[cannot-spread-indexer] #8276
248-
aggregated: getAggregatedPresence({
249-
...oldUserPresence,
241+
byEmail: state.byEmail.update(action.email, (userPresence: UserPresence): UserPresence =>
242+
// $FlowIssue[cannot-spread-indexer] https://github.com/facebook/flow/issues/8276
243+
({
244+
...userPresence,
250245
...action.presence,
246+
// $FlowIssue[cannot-spread-indexer] https://github.com/facebook/flow/issues/8276
247+
aggregated: getAggregatedPresence({
248+
...userPresence,
249+
...action.presence,
250+
}),
251251
}),
252-
},
252+
),
253253
};
254254
}
255+
255256
default:
256257
return state;
257258
}

src/reduxTypes.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ export type OutboxState = $ReadOnlyArray<Outbox>;
218218
* presence status.
219219
*/
220220
export type PresenceState = $ReadOnly<{|
221-
[email: string]: UserPresence,
221+
byEmail: Immutable.Map<string, UserPresence>,
222222
|}>;
223223

224224
/**

src/storage/migrations.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,8 @@ const migrationsInner: {| [string]: (LessPartialState) => LessPartialState |} =
505505
// Change `state.mute` data structure: was a plain JS Map.
506506
'59': dropCache,
507507

508+
// Changed `state.presence`, but no migration because that's in `discardKeys`.
509+
508510
// TIP: When adding a migration, consider just using `dropCache`.
509511
// (See its jsdoc for guidance on when that's the right answer.)
510512
};

0 commit comments

Comments
 (0)