2020-10-30 20:34:04 +00:00
|
|
|
// Copyright 2020 Signal Messenger, LLC
|
|
|
|
// SPDX-License-Identifier: AGPL-3.0-only
|
|
|
|
|
2023-01-13 20:07:26 +00:00
|
|
|
import type { ReadonlyDeep } from 'type-fest';
|
2020-02-12 21:30:58 +00:00
|
|
|
import { SocketStatus } from '../../types/SocketStatus';
|
|
|
|
import { trigger } from '../../shims/events';
|
2020-12-16 01:57:34 +00:00
|
|
|
import { assignWithNoUnnecessaryAllocation } from '../../util/assignWithNoUnnecessaryAllocation';
|
2020-02-12 21:30:58 +00:00
|
|
|
|
|
|
|
// State
|
|
|
|
|
2023-01-13 20:07:26 +00:00
|
|
|
export type NetworkStateType = ReadonlyDeep<{
|
2020-02-12 21:30:58 +00:00
|
|
|
isOnline: boolean;
|
|
|
|
socketStatus: SocketStatus;
|
|
|
|
withinConnectingGracePeriod: boolean;
|
2021-05-06 00:09:29 +00:00
|
|
|
challengeStatus: 'required' | 'pending' | 'idle';
|
2023-01-13 20:07:26 +00:00
|
|
|
}>;
|
2020-02-12 21:30:58 +00:00
|
|
|
|
|
|
|
// Actions
|
|
|
|
|
|
|
|
const CHECK_NETWORK_STATUS = 'network/CHECK_NETWORK_STATUS';
|
|
|
|
const CLOSE_CONNECTING_GRACE_PERIOD = 'network/CLOSE_CONNECTING_GRACE_PERIOD';
|
|
|
|
const RELINK_DEVICE = 'network/RELINK_DEVICE';
|
2021-05-06 00:09:29 +00:00
|
|
|
const SET_CHALLENGE_STATUS = 'network/SET_CHALLENGE_STATUS';
|
2020-02-12 21:30:58 +00:00
|
|
|
|
2023-01-13 20:07:26 +00:00
|
|
|
export type CheckNetworkStatusPayloadType = ReadonlyDeep<{
|
2020-02-12 21:30:58 +00:00
|
|
|
isOnline: boolean;
|
|
|
|
socketStatus: SocketStatus;
|
2023-01-13 20:07:26 +00:00
|
|
|
}>;
|
2020-02-12 21:30:58 +00:00
|
|
|
|
2023-01-13 20:07:26 +00:00
|
|
|
type CheckNetworkStatusAction = ReadonlyDeep<{
|
2020-02-12 21:30:58 +00:00
|
|
|
type: 'network/CHECK_NETWORK_STATUS';
|
|
|
|
payload: CheckNetworkStatusPayloadType;
|
2023-01-13 20:07:26 +00:00
|
|
|
}>;
|
2020-02-12 21:30:58 +00:00
|
|
|
|
2023-01-13 20:07:26 +00:00
|
|
|
type CloseConnectingGracePeriodActionType = ReadonlyDeep<{
|
2020-02-12 21:30:58 +00:00
|
|
|
type: 'network/CLOSE_CONNECTING_GRACE_PERIOD';
|
2023-01-13 20:07:26 +00:00
|
|
|
}>;
|
2020-02-12 21:30:58 +00:00
|
|
|
|
2023-01-13 20:07:26 +00:00
|
|
|
type RelinkDeviceActionType = ReadonlyDeep<{
|
2020-02-12 21:30:58 +00:00
|
|
|
type: 'network/RELINK_DEVICE';
|
2023-01-13 20:07:26 +00:00
|
|
|
}>;
|
2020-02-12 21:30:58 +00:00
|
|
|
|
2023-01-13 20:07:26 +00:00
|
|
|
type SetChallengeStatusActionType = ReadonlyDeep<{
|
2021-05-06 00:09:29 +00:00
|
|
|
type: 'network/SET_CHALLENGE_STATUS';
|
|
|
|
payload: {
|
|
|
|
challengeStatus: NetworkStateType['challengeStatus'];
|
|
|
|
};
|
2023-01-13 20:07:26 +00:00
|
|
|
}>;
|
2021-05-06 00:09:29 +00:00
|
|
|
|
2023-01-13 20:07:26 +00:00
|
|
|
export type NetworkActionType = ReadonlyDeep<
|
2020-02-12 21:30:58 +00:00
|
|
|
| CheckNetworkStatusAction
|
|
|
|
| CloseConnectingGracePeriodActionType
|
2021-05-06 00:09:29 +00:00
|
|
|
| RelinkDeviceActionType
|
2023-01-13 20:07:26 +00:00
|
|
|
| SetChallengeStatusActionType
|
|
|
|
>;
|
2020-02-12 21:30:58 +00:00
|
|
|
|
|
|
|
// Action Creators
|
|
|
|
|
|
|
|
function checkNetworkStatus(
|
|
|
|
payload: CheckNetworkStatusPayloadType
|
|
|
|
): CheckNetworkStatusAction {
|
|
|
|
return {
|
|
|
|
type: CHECK_NETWORK_STATUS,
|
|
|
|
payload,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
function closeConnectingGracePeriod(): CloseConnectingGracePeriodActionType {
|
|
|
|
return {
|
|
|
|
type: CLOSE_CONNECTING_GRACE_PERIOD,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
function relinkDevice(): RelinkDeviceActionType {
|
|
|
|
trigger('setupAsNewDevice');
|
|
|
|
|
|
|
|
return {
|
|
|
|
type: RELINK_DEVICE,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2021-05-06 00:09:29 +00:00
|
|
|
function setChallengeStatus(
|
|
|
|
challengeStatus: NetworkStateType['challengeStatus']
|
|
|
|
): SetChallengeStatusActionType {
|
|
|
|
return {
|
|
|
|
type: SET_CHALLENGE_STATUS,
|
|
|
|
payload: { challengeStatus },
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2020-02-12 21:30:58 +00:00
|
|
|
export const actions = {
|
|
|
|
checkNetworkStatus,
|
|
|
|
closeConnectingGracePeriod,
|
|
|
|
relinkDevice,
|
2021-05-06 00:09:29 +00:00
|
|
|
setChallengeStatus,
|
2020-02-12 21:30:58 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
// Reducer
|
|
|
|
|
2021-05-06 00:09:29 +00:00
|
|
|
export function getEmptyState(): NetworkStateType {
|
2020-02-12 21:30:58 +00:00
|
|
|
return {
|
|
|
|
isOnline: navigator.onLine,
|
2021-06-09 22:28:54 +00:00
|
|
|
socketStatus: SocketStatus.OPEN,
|
2020-02-12 21:30:58 +00:00
|
|
|
withinConnectingGracePeriod: true,
|
2021-05-06 00:09:29 +00:00
|
|
|
challengeStatus: 'idle',
|
2020-02-12 21:30:58 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
export function reducer(
|
2020-12-14 19:47:21 +00:00
|
|
|
state: Readonly<NetworkStateType> = getEmptyState(),
|
|
|
|
action: Readonly<NetworkActionType>
|
2020-02-12 21:30:58 +00:00
|
|
|
): NetworkStateType {
|
|
|
|
if (action.type === CHECK_NETWORK_STATUS) {
|
|
|
|
const { isOnline, socketStatus } = action.payload;
|
|
|
|
|
2020-12-16 01:57:34 +00:00
|
|
|
// This action is dispatched frequently. We avoid allocating a new object if nothing
|
|
|
|
// has changed to avoid an unnecessary re-render.
|
|
|
|
return assignWithNoUnnecessaryAllocation(state, {
|
2020-02-12 21:30:58 +00:00
|
|
|
isOnline,
|
|
|
|
socketStatus,
|
2020-12-16 01:57:34 +00:00
|
|
|
});
|
2020-02-12 21:30:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (action.type === CLOSE_CONNECTING_GRACE_PERIOD) {
|
|
|
|
return {
|
|
|
|
...state,
|
|
|
|
withinConnectingGracePeriod: false,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2021-05-06 00:09:29 +00:00
|
|
|
if (action.type === SET_CHALLENGE_STATUS) {
|
|
|
|
return {
|
|
|
|
...state,
|
|
|
|
challengeStatus: action.payload.challengeStatus,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2020-02-12 21:30:58 +00:00
|
|
|
return state;
|
|
|
|
}
|