Skip to content

Commit

Permalink
feat: Degraded Conversation - plain indication
Browse files Browse the repository at this point in the history
  • Loading branch information
przemvs committed Nov 23, 2023
1 parent 3943102 commit 0cea9a7
Show file tree
Hide file tree
Showing 23 changed files with 351 additions and 56 deletions.
4 changes: 4 additions & 0 deletions src/i18n/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -1335,6 +1335,10 @@
"tooltipConversationAllDevicesVerified": "All device fingerprints verified (Proteus)",
"tooltipConversationAllE2EIVerified": "All devices are verified (end-to-end identity). [link]Learn more[/link]",
"tooltipConversationAllE2EIVerifiedShort": "All devices verified (end-to-end identity)",
"tooltipConversationAllE2EINewDeviceAdded": "This conversation is no longer verified, as [bold]{{user}}[/bold] uses at least one device without a valid end-to-end identity certificate.",
"tooltipConversationAllE2EINewUserAdded": "This conversation is no longer verified, as [bold]{{user}}[/bold] uses at least one device without a valid end-to-end identity certificate.",
"tooltipConversationAllE2EICertificateExpired": "This conversation is no longer verified, as [bold]{{user}}[/bold] uses at least one devices with an expired end-to-end identity certificate.",
"tooltipConversationAllE2EICertificateRevoked": "This conversation is no longer verified, as a team admin revoked the end-to-end identity certificate for at least one of [bold]{{user}}[/bold] devices. [link]Learn more[/link]",
"tooltipConversationCall": "Call",
"tooltipConversationDetailsAddPeople": "Add participants to conversation ({{shortcut}})",
"tooltipConversationDetailsRename": "Change conversation name",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Wire
* Copyright (C) 2022 Wire Swiss GmbH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://www.gnu.org/licenses/.
*
*/

import {CSSObject} from '@emotion/react';

export const MessageIcon: CSSObject = {
alignItems: 'center',
display: 'flex',
justifyContent: 'center',

maxHeight: 'var(--avatar-diameter-s)',
width: 'var(--conversation-message-sender-width)',
};

export const IconInfo: CSSObject = {
fill: 'var(--red-500)',
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Wire
* Copyright (C) 2021 Wire Swiss GmbH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://www.gnu.org/licenses/.
*
*/

import {render} from '@testing-library/react';
import ko from 'knockout';

import {E2EIVerificationMessage as VerificationMessageEntity} from 'src/script/entity/message/E2EIVerificationMessage';
import {E2EIVerificationMessageType} from 'src/script/message/E2EIVerificationMessageType';

import {E2EIVerificationMessage} from './E2EIVerificationMessage';

import {withTheme} from '../../../../auth/util/test/TestUtil';

const createVerificationMessage = (partialVerificationMessage: Partial<VerificationMessageEntity>) => {
const verificationMessage: Partial<VerificationMessageEntity> = {
...partialVerificationMessage,
};
return verificationMessage as VerificationMessageEntity;
};

describe('E2EIVerificationMessage', () => {
describe('with verified message', () => {
it('shows verified icon when message is verified', async () => {
const message = createVerificationMessage({
messageType: ko.observable<E2EIVerificationMessageType>(E2EIVerificationMessageType.VERIFIED),
});

const {getByTestId} = render(withTheme(<E2EIVerificationMessage message={message} />));

const elementMessageVerification = getByTestId('element-message-verification');
expect(elementMessageVerification.getAttribute('data-uie-value')).toEqual(E2EIVerificationMessageType.VERIFIED);
});
});

// TODO: Add more test for another e2ei verification states
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/*
* Wire
* Copyright (C) 2023 Wire Swiss GmbH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://www.gnu.org/licenses/.
*
*/

import {MLSVerified} from '@wireapp/react-ui-kit';

import {Icon} from 'Components/Icon';
import {useKoSubscribableChildren} from 'Util/ComponentUtil';
import {replaceLink, t} from 'Util/LocalizerUtil';

import {MessageIcon, IconInfo} from './E2EIVerificationMessage.styles';

import {Config} from '../../../../Config';
import {E2EIVerificationMessage as E2EIVerificationMessageEntity} from '../../../../entity/message/E2EIVerificationMessage';
import {E2EIVerificationMessageType} from '../../../../message/E2EIVerificationMessageType';

export interface E2EIVerificationMessageProps {
message: E2EIVerificationMessageEntity;
}

export const E2EIVerificationMessage = ({message}: E2EIVerificationMessageProps) => {
const {messageType} = useKoSubscribableChildren(message, ['messageType']);

const user = 'Deniz Agha';

const isVerified = messageType === E2EIVerificationMessageType.VERIFIED;
const isUnverified = messageType === E2EIVerificationMessageType.UNVERIFIED;
const isNewDevice = messageType === E2EIVerificationMessageType.NEW_DEVICE;
const isNewMember = messageType === E2EIVerificationMessageType.NEW_MEMBER;
const isDegraded = messageType === E2EIVerificationMessageType.DEGRADED;

const learnMoreReplacement = replaceLink(Config.getConfig().URL.SUPPORT.E2EI_VERIFICATION);

return (
<div className="message-header">
<div css={MessageIcon}>
{isVerified ? (
<MLSVerified data-uie-name="conversation-title-bar-verified-icon" />
) : (
<Icon.Info css={IconInfo} />
)}
</div>

<div
className="message-header-label message-header-label--verification"
data-uie-name="element-message-verification"
data-uie-value={messageType}
>
{isVerified && (
<span
dangerouslySetInnerHTML={{
__html: t('tooltipConversationAllE2EIVerified', {}, learnMoreReplacement),
}}
/>
)}

{isNewDevice && (
<span
dangerouslySetInnerHTML={{
__html: t('tooltipConversationAllE2EINewDeviceAdded', {user}),
}}
/>
)}

{isNewMember && (
<span
dangerouslySetInnerHTML={{
__html: t('tooltipConversationAllE2EINewUserAdded', {user}),
}}
/>
)}

{isUnverified && (
<span
dangerouslySetInnerHTML={{
__html: t('tooltipConversationAllE2EINewUserAdded', {user}),
}}
/>
)}

{isDegraded && (
<span
dangerouslySetInnerHTML={{
__html: t('tooltipConversationAllE2EICertificateRevoked', {user}, learnMoreReplacement),
}}
/>
)}
</div>
</div>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* Wire
* Copyright (C) 2023 Wire Swiss GmbH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://www.gnu.org/licenses/.
*
*/

export * from './E2EIVerificationMessage';
4 changes: 4 additions & 0 deletions src/script/components/MessagesList/Message/MessageWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {container} from 'tsyringe';

import {WebAppEvents} from '@wireapp/webapp-events';

import {E2EIVerificationMessage} from 'Components/MessagesList/Message/E2EIVerificationMessage';
import {OutgoingQuote} from 'src/script/conversation/MessageRepository';
import {ContentMessage} from 'src/script/entity/message/ContentMessage';
import {Text} from 'src/script/entity/message/Text';
Expand Down Expand Up @@ -220,6 +221,9 @@ export const MessageWrapper: React.FC<MessageParams & {hasMarker: boolean; isMes
if (message.isVerification()) {
return <VerificationMessage message={message} />;
}
if (message.isE2EIVerification()) {
return <E2EIVerificationMessage message={message} />;
}
if (message.isDelete()) {
return <DeleteMessage message={message} onClickAvatar={onClickAvatar} />;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,7 @@

import React from 'react';

import {MLSVerified} from '@wireapp/react-ui-kit';

import {Icon} from 'Components/Icon';
import {E2EIVerificationMessage} from 'src/script/entity/message/E2EIVerificationMessage';
import {MessageTimerUpdateMessage} from 'src/script/entity/message/MessageTimerUpdateMessage';
import {MLSConversationRecoveredMessage} from 'src/script/entity/message/MLSConversationRecoveredMessage';
import {ReceiptModeUpdateMessage} from 'src/script/entity/message/ReceiptModeUpdateMessage';
Expand Down Expand Up @@ -57,9 +54,5 @@ export const SystemMessage: React.FC<SystemMessageProps> = ({message}) => {
return <SystemMessageBase message={message} icon={<Icon.Info />} />;
}

if (message instanceof E2EIVerificationMessage) {
return <SystemMessageBase message={message} icon={<MLSVerified className="filled" />} />;
}

return <SystemMessageBase message={message} />;
};
3 changes: 1 addition & 2 deletions src/script/conversation/ConversationCellState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ import type {MemberMessage} from '../entity/message/MemberMessage';
import type {SystemMessage} from '../entity/message/SystemMessage';
import type {Text} from '../entity/message/Text';
import {ConversationError} from '../error/ConversationError';
import {ClientEvent} from '../event/Client';

enum ACTIVITY_TYPE {
CALL = 'ConversationCellState.ACTIVITY_TYPE.CALL',
Expand Down Expand Up @@ -335,7 +334,7 @@ const _getStateUnreadMessage = {
string = t('notificationSharedLocation');
} else if (messageEntity.hasAssetImage()) {
string = t('notificationAssetAdd');
} else if (messageEntity?.type === ClientEvent.CONVERSATION.E2EI_VERIFICATION) {
} else if (messageEntity.isE2EIVerification()) {
string = t('tooltipConversationAllDevicesVerified');
} else if (messageEntity.isVerification()) {
string = t('tooltipConversationAllDevicesVerified');
Expand Down
2 changes: 1 addition & 1 deletion src/script/conversation/ConversationRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2879,9 +2879,9 @@ export class ConversationRepository {
case ClientEvent.CONVERSATION.MLS_CONVERSATION_RECOVERED:
case ClientEvent.CONVERSATION.UNABLE_TO_DECRYPT:
case ClientEvent.CONVERSATION.VERIFICATION:
case ClientEvent.CONVERSATION.E2EI_VERIFICATION:
case ClientEvent.CONVERSATION.VOICE_CHANNEL_ACTIVATE:
case ClientEvent.CONVERSATION.VOICE_CHANNEL_DEACTIVATE:
case ClientEvent.CONVERSATION.E2EI_VERIFICATION:
return this.addEventToConversation(conversationEntity, eventJson);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,20 @@ import {container} from 'tsyringe';

import {MLSStatuses} from 'Components/VerificationBadge';
import {getConversationVerificationState, getUsersVerificationState} from 'src/script/E2EIdentity';
import {VerificationMessageType} from 'src/script/message/VerificationMessageType';
import {E2EIVerificationMessageType} from 'src/script/message/E2EIVerificationMessageType';
import {Core} from 'src/script/service/CoreSingleton';
import {Logger, getLogger} from 'Util/Logger';

import {MLSConversation} from '../../ConversationSelectors';
import {ConversationState} from '../../ConversationState';
import {ConversationVerificationState} from '../../ConversationVerificationState';
import {getConversationByGroupId, OnConversationVerificationStateChange} from '../shared';
import {getConversationByGroupId, OnConversationE2EIVerificationStateChange} from '../shared';

class MLSConversationVerificationStateHandler {
private readonly logger: Logger;

public constructor(
private readonly onConversationVerificationStateChange: OnConversationVerificationStateChange,
private readonly onConversationVerificationStateChange: OnConversationE2EIVerificationStateChange,
private readonly conversationState: ConversationState,
private readonly core: Core,
) {
Expand Down Expand Up @@ -64,7 +64,7 @@ class MLSConversationVerificationStateHandler {
this.onConversationVerificationStateChange({
conversationEntity: conversation,
conversationVerificationState: state,
verificationMessageType: VerificationMessageType.UNVERIFIED,
verificationMessageType: E2EIVerificationMessageType.UNVERIFIED,
userIds: degradedUsers,
});
}
Expand Down Expand Up @@ -107,7 +107,7 @@ class MLSConversationVerificationStateHandler {
}

export const registerMLSConversationVerificationStateHandler = (
onConversationVerificationStateChange: OnConversationVerificationStateChange = () => {},
onConversationVerificationStateChange: OnConversationE2EIVerificationStateChange = () => {},
conversationState: ConversationState = container.resolve(ConversationState),
core: Core = container.resolve(Core),
): void => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,24 @@ import {ConversationVerificationState} from 'src/script/conversation/Conversatio
import {Conversation} from 'src/script/entity/Conversation';
import {VerificationMessageType} from 'src/script/message/VerificationMessageType';

interface OnConversationVerificationStateChangeParams {
import {E2EIVerificationMessageType} from '../../../../message/E2EIVerificationMessageType';

interface CommonOnConversationVerificationStateChangeParams {
conversationEntity: Conversation;
conversationVerificationState: ConversationVerificationState;
verificationMessageType?: VerificationMessageType;
userIds?: QualifiedId[];
}

interface OnConversationVerificationStateChangeParams extends CommonOnConversationVerificationStateChangeParams {
verificationMessageType?: VerificationMessageType;
}

interface OnConversationE2EIVerificationStateChangeParams extends CommonOnConversationVerificationStateChangeParams {
verificationMessageType?: E2EIVerificationMessageType;
}

export type OnConversationVerificationStateChange = (params: OnConversationVerificationStateChangeParams) => void;

export type OnConversationE2EIVerificationStateChange = (
params: OnConversationE2EIVerificationStateChangeParams,
) => void;
Loading

0 comments on commit 0cea9a7

Please sign in to comment.