Merge pull request #1744 from Bilb/use-retrieve-status-for-isOnline

use our retrieve status as isOnline status
pull/1747/head
Audric Ackermann 4 years ago committed by GitHub
commit a0811b699c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -450,7 +450,6 @@
}, window.CONSTANTS.NOTIFICATION_ENABLE_TIMEOUT_SECONDS * 1000);
window.NewReceiver.queueAllCached();
window.libsession.Utils.AttachmentDownloads.start({
logger: window.log,
});

@ -7,7 +7,6 @@ import { openConversationExternal } from '../state/ducks/conversations';
import { LeftPaneContactSection } from './session/LeftPaneContactSection';
import { LeftPaneSettingSection } from './session/LeftPaneSettingSection';
import { SessionTheme } from '../state/ducks/SessionTheme';
import { SessionOffline } from './session/network/SessionOffline';
import { SessionExpiredWarning } from './session/network/SessionExpiredWarning';
import { getFocusedSection } from '../state/selectors/section';
import { useDispatch, useSelector } from 'react-redux';
@ -44,7 +43,6 @@ const InnerLeftPaneMessageSection = (props: { isExpired: boolean }) => {
return (
<>
<SessionOffline />
{props.isExpired && <SessionExpiredWarning />}
<LeftPaneMessageSection
theme={theme}
@ -74,7 +72,6 @@ const InnerLeftPaneContactSection = () => {
return (
<>
<SessionOffline />
<LeftPaneContactSection
openConversationExternal={(id, messageId) =>
dispatch(openConversationExternal(id, messageId))

@ -20,11 +20,10 @@ import { onionPathModal } from '../state/ducks/modalDialog';
import {
getFirstOnionPath,
getFirstOnionPathLength,
getIsOnline,
getOnionPathsCount,
} from '../state/selectors/onions';
// tslint:disable-next-line: no-submodule-imports
import useNetworkState from 'react-use/lib/useNetworkState';
import { SessionSpinner } from './session/SessionSpinner';
import { Flex } from './basic/Flex';
@ -36,9 +35,10 @@ export type StatusLightType = {
const OnionPathModalInner = () => {
const onionPath = useSelector(getFirstOnionPath);
const isOnline = useSelector(getIsOnline);
// including the device and destination in calculation
const glowDuration = onionPath.length + 2;
if (!onionPath || onionPath.length === 0) {
if (!isOnline || !onionPath || onionPath.length === 0) {
return <SessionSpinner loading={true} />;
}
@ -144,7 +144,7 @@ export const ActionPanelOnionStatusLight = (props: {
const theme = useTheme();
const onionPathsCount = useSelector(getOnionPathsCount);
const firstPathLength = useSelector(getFirstOnionPathLength);
const isOnline = useNetworkState().online;
const isOnline = useSelector(getIsOnline);
// Set icon color based on result
const red = theme.colors.destructive;
@ -164,6 +164,9 @@ export const ActionPanelOnionStatusLight = (props: {
iconType={SessionIconType.Circle}
iconColor={iconColor}
onClick={handleClick}
glowDuration={10}
glowStartDelay={0}
noScale={true}
isSelected={isSelected}
theme={theme}
/>

@ -12,6 +12,7 @@ export type SessionIconProps = {
glowDuration?: number;
borderRadius?: number;
glowStartDelay?: number;
noScale?: boolean;
theme?: DefaultTheme;
};
@ -46,6 +47,7 @@ type StyledSvgProps = {
borderRadius?: number;
glowDuration?: number;
glowStartDelay?: number;
noScale?: boolean;
iconColor?: string;
};
@ -91,16 +93,22 @@ const animation = (props: {
glowDuration?: number;
glowStartDelay?: number;
iconColor?: string;
noScale?: boolean;
}) => {
if (props.rotateDuration) {
return css`
${rotate} ${props.rotateDuration}s infinite linear;
`;
} else if (
props.glowDuration !== undefined &&
props.glowStartDelay !== undefined &&
props.iconColor
) {
}
if (props.noScale) {
return css``;
}
if (props.glowDuration === 10) {
console.warn('scake', props);
}
if (props.glowDuration !== undefined && props.glowStartDelay !== undefined && props.iconColor) {
return css`
${glow(
props.iconColor,
@ -108,9 +116,9 @@ const animation = (props: {
props.glowStartDelay
)} ${props.glowDuration}s ease infinite;
`;
} else {
return;
}
return;
};
//tslint:disable no-unnecessary-callback-wrapper
@ -119,6 +127,7 @@ const Svg = styled.svg<StyledSvgProps>`
transform: ${props => `rotate(${props.iconRotation}deg)`};
animation: ${props => animation(props)};
border-radius: ${props => props.borderRadius};
filter: ${props => (props.noScale ? `drop-shadow(0px 0px 4px ${props.iconColor})` : '')};
`;
//tslint:enable no-unnecessary-callback-wrapper
@ -132,6 +141,7 @@ const SessionSvg = (props: {
rotateDuration?: number;
glowDuration?: number;
glowStartDelay?: number;
noScale?: boolean;
borderRadius?: number;
theme: DefaultTheme;
}) => {
@ -146,6 +156,7 @@ const SessionSvg = (props: {
glowDuration: props.glowDuration,
glowStartDelay: props.glowStartDelay,
iconColor: props.iconColor,
noScale: props.noScale,
};
return (
@ -166,6 +177,7 @@ export const SessionIcon = (props: SessionIconProps) => {
glowDuration,
borderRadius,
glowStartDelay,
noScale,
} = props;
let { iconSize, iconRotation } = props;
iconSize = iconSize || SessionIconSize.Medium;
@ -189,6 +201,7 @@ export const SessionIcon = (props: SessionIconProps) => {
rotateDuration={rotateDuration}
glowDuration={glowDuration}
glowStartDelay={glowStartDelay}
noScale={noScale}
borderRadius={borderRadius}
iconRotation={iconRotation}
iconColor={iconColor}

@ -20,6 +20,9 @@ export const SessionIconButton = (props: SProps) => {
isSelected,
notificationCount,
theme,
glowDuration,
glowStartDelay,
noScale,
} = props;
const clickHandler = (e: any) => {
if (props.onClick) {
@ -42,6 +45,9 @@ export const SessionIconButton = (props: SProps) => {
iconColor={iconColor}
iconRotation={iconRotation}
theme={themeToUSe}
glowDuration={glowDuration}
glowStartDelay={glowStartDelay}
noScale={noScale}
/>
{Boolean(notificationCount) && <SessionNotificationCount count={notificationCount} />}
</div>

@ -1,36 +0,0 @@
import React from 'react';
// tslint:disable-next-line: no-submodule-imports
import useNetworkState from 'react-use/lib/useNetworkState';
import styled from 'styled-components';
type ContainerProps = {
show: boolean;
};
const OfflineContainer = styled.div<ContainerProps>`
background: ${props => props.theme.colors.accent};
color: ${props => props.theme.colors.textColor};
padding: ${props => (props.show ? props.theme.common.margins.sm : '0px')};
margin: ${props => (props.show ? props.theme.common.margins.xs : '0px')};
height: ${props => (props.show ? 'auto' : '0px')};
overflow: hidden;
transition: ${props => props.theme.common.animations.defaultDuration};
`;
const OfflineTitle = styled.h3`
padding-top: 0px;
margin-top: 0px;
`;
const OfflineMessage = styled.div``;
export const SessionOffline = () => {
const isOnline = useNetworkState().online;
return (
<OfflineContainer show={!isOnline}>
<OfflineTitle>{window.i18n('offline')}</OfflineTitle>
<OfflineMessage>{window.i18n('checkNetworkConnection')}</OfflineMessage>
</OfflineContainer>
);
};

@ -846,7 +846,7 @@ export class MessageModel extends Backbone.Model<MessageAttributes> {
const chatParams = {
identifier: this.id,
body,
timestamp: this.get('sent_at') || Date.now(),
timestamp: Date.now(), // force a new timestamp to handle user fixed his clock
expireTimer: this.get('expireTimer'),
attachments,
preview,

@ -179,7 +179,7 @@ export const sendViaOnion = async (
{
retries: 9, // each path can fail 3 times before being dropped, we have 3 paths at most
factor: 2,
minTimeout: 1000,
minTimeout: 100,
maxTimeout: 4000,
onFailedAttempt: e => {
window?.log?.warn(

@ -70,11 +70,11 @@ export async function sendMessage(
);
throw e;
}
if (!snode) {
if (!usedNodes || usedNodes.length === 0) {
throw new window.textsecure.EmptySwarmError(pubKey, 'Ran out of swarm nodes to query');
} else {
window?.log?.info(
`loki_message:::sendMessage - Successfully stored message to ${pubKey} via ${snode.ip}:${snode.port}`
);
}
window?.log?.info(
`loki_message:::sendMessage - Successfully stored message to ${pubKey} via ${snode.ip}:${snode.port}`
);
}

@ -24,11 +24,14 @@ import {
toHex,
} from '../utils/String';
import { Snode } from '../../data/data';
import { updateIsOnline } from '../../state/ducks/onion';
// ONS name can have [a-zA-Z0-9_-] except that - is not allowed as start or end
// do not define a regex but rather create it on the fly to avoid https://stackoverflow.com/questions/3891641/regex-test-only-works-every-other-time
export const onsNameRegex = '^\\w([\\w-]*[\\w])?$';
export const ERROR_CODE_NO_CONNECT = 'ENETUNREACH: No network connection.';
const getSslAgentForSeedNode = (seedNodeHost: string, isSsl = false) => {
let filePrefix = '';
let pubkey256 = '';
@ -493,8 +496,8 @@ export async function storeOnNode(targetNode: Snode, params: SendParams): Promis
e,
`destination ${targetNode.ip}:${targetNode.port}`
);
throw e;
}
return false;
}
/** */
@ -527,9 +530,12 @@ export async function retrieveNextMessages(
try {
const json = JSON.parse(result.body);
window.inboxStore?.dispatch(updateIsOnline(true));
return json.messages || [];
} catch (e) {
window?.log?.warn('exception while parsing json of nextMessage:', e);
window.inboxStore?.dispatch(updateIsOnline(true));
return [];
}
@ -538,6 +544,11 @@ export async function retrieveNextMessages(
'Got an error while retrieving next messages. Not retrying as we trigger fetch often:',
e
);
if (e.message === ERROR_CODE_NO_CONNECT) {
window.inboxStore?.dispatch(updateIsOnline(false));
} else {
window.inboxStore?.dispatch(updateIsOnline(true));
}
return [];
}
}

@ -13,6 +13,7 @@ import { hrefPnServerDev, hrefPnServerProd } from '../../pushnotification/PnServ
let snodeFailureCount: Record<string, number> = {};
import { Snode } from '../../data/data';
import { ERROR_CODE_NO_CONNECT } from './SNodeAPI';
// tslint:disable-next-line: variable-name
export const TEST_resetSnodeFailureCount = () => {
@ -37,6 +38,9 @@ export interface SnodeResponse {
export const NEXT_NODE_NOT_FOUND_PREFIX = 'Next node not found: ';
export const CLOCK_OUT_OF_SYNC_MESSAGE_ERROR =
'Your clock is out of sync with the network. Check your clock.';
// Returns the actual ciphertext, symmetric key that will be used
// for decryption, and an ephemeral_key to send to the next hop
async function encryptForPubKey(pubKeyX25519hex: string, reqObj: any): Promise<DestinationContext> {
@ -195,9 +199,8 @@ async function buildOnionGuardNodePayload(
function process406Error(statusCode: number) {
if (statusCode === 406) {
// clock out of sync
console.warn('clock out of sync todo');
// this will make the pRetry stop
throw new pRetry.AbortError('You clock is out of sync with the network. Check your clock.');
throw new pRetry.AbortError(CLOCK_OUT_OF_SYNC_MESSAGE_ERROR);
}
}
@ -783,6 +786,7 @@ const sendOnionRequest = async ({
// we are talking to a snode...
agent: snodeHttpsAgent,
abortSignal,
timeout: 5000,
};
const guardUrl = `https://${guardNode.ip}:${guardNode.port}/onion_req/v2`;
@ -859,7 +863,7 @@ export async function lokiOnionFetch(
return onionFetchRetryable(targetNode, body, associatedWith);
},
{
retries: 9,
retries: 4,
factor: 1,
minTimeout: 1000,
maxTimeout: 2000,
@ -875,6 +879,14 @@ export async function lokiOnionFetch(
} catch (e) {
window?.log?.warn('onionFetchRetryable failed ', e);
// console.warn('error to show to user');
if (e?.errno === 'ENETUNREACH') {
// better handle the no connection state
throw new Error(ERROR_CODE_NO_CONNECT);
}
if (e?.message === CLOCK_OUT_OF_SYNC_MESSAGE_ERROR) {
window?.log?.warn('Its an clock out of sync error ');
throw new pRetry.AbortError(CLOCK_OUT_OF_SYNC_MESSAGE_ERROR);
}
throw e;
}
}

@ -51,7 +51,6 @@ export const getSwarmPollingInstance = () => {
};
export class SwarmPolling {
private ourPubkey: PubKey | undefined;
private groupPolling: Array<{ pubkey: PubKey; lastPolledTimestamp: number }>;
private readonly lastHashes: { [key: string]: PubkeyToHash };
@ -61,7 +60,6 @@ export class SwarmPolling {
}
public async start(waitForFirstPoll = false): Promise<void> {
this.ourPubkey = UserUtils.getOurPubKeyFromCache();
this.loadGroupIds();
if (waitForFirstPoll) {
await this.TEST_pollForAllKeys();
@ -74,7 +72,6 @@ export class SwarmPolling {
* Used fo testing only
*/
public TEST_reset() {
this.ourPubkey = undefined;
this.groupPolling = [];
}
@ -88,10 +85,6 @@ export class SwarmPolling {
public removePubkey(pk: PubKey | string) {
const pubkey = PubKey.cast(pk);
window?.log?.info('Swarm removePubkey: removing pubkey from polling', pubkey.key);
if (this.ourPubkey && PubKey.cast(pk).isEqual(this.ourPubkey)) {
this.ourPubkey = undefined;
}
this.groupPolling = this.groupPolling.filter(group => !pubkey.isEqual(group.pubkey));
}
@ -132,9 +125,8 @@ export class SwarmPolling {
*/
public async TEST_pollForAllKeys() {
// we always poll as often as possible for our pubkey
const directPromise = this.ourPubkey
? this.TEST_pollOnceForKey(this.ourPubkey, false)
: Promise.resolve();
const ourPubkey = UserUtils.getOurPubKeyFromCache();
const directPromise = this.TEST_pollOnceForKey(ourPubkey, false);
const now = Date.now();
const groupPromises = this.groupPolling.map(async group => {

@ -3,10 +3,12 @@ import { Snode } from '../../data/data';
export type OnionState = {
snodePaths: Array<Array<Snode>>;
isOnline: boolean;
};
export const initialOnionPathState = {
snodePaths: new Array<Array<Snode>>(),
isOnline: false,
};
/**
@ -17,12 +19,15 @@ const onionSlice = createSlice({
initialState: initialOnionPathState,
reducers: {
updateOnionPaths(state: OnionState, action: PayloadAction<Array<Array<Snode>>>) {
return { snodePaths: action.payload };
return { ...state, snodePaths: action.payload };
},
updateIsOnline(state: OnionState, action: PayloadAction<boolean>) {
return { ...state, isOnline: action.payload };
},
},
});
// destructures
const { actions, reducer } = onionSlice;
export const { updateOnionPaths } = actions;
export const { updateOnionPaths, updateIsOnline } = actions;
export const defaultOnionReducer = reducer;

@ -21,3 +21,8 @@ export const getFirstOnionPathLength = createSelector(
getFirstOnionPath,
(state: Array<Snode>): number => state.length || 0
);
export const getIsOnline = createSelector(
getOnionPaths,
(state: OnionState): boolean => state.isOnline
);

@ -216,7 +216,7 @@ describe('OnionPathsErrors', () => {
throw new Error('Error expected');
} catch (e) {
expect(e.message).to.equal(
'You clock is out of sync with the network. Check your clock.'
'Your clock is out of sync with the network. Check your clock.'
);
// this makes sure that this call would not be retried
expect(e.name).to.equal('AbortError');
@ -237,7 +237,7 @@ describe('OnionPathsErrors', () => {
throw new Error('Error expected');
} catch (e) {
expect(e.message).to.equal(
'You clock is out of sync with the network. Check your clock.'
'Your clock is out of sync with the network. Check your clock.'
);
// this makes sure that this call would not be retried
expect(e.name).to.equal('AbortError');

Loading…
Cancel
Save