diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 916bfda27..21ce72678 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -19,6 +19,8 @@ "editMenuPaste": "Paste", "editMenuPasteAndMatchStyle": "Paste and Match Style", "editMenuDelete": "Delete", + "editMenuDeleteContact": "Delete Contact", + "editMenuDeleteGroup": "Delete Group", "editMenuSelectAll": "Select all", "windowMenuClose": "Close Window", "windowMenuMinimize": "Minimize", diff --git a/package.json b/package.json index ae5d8b26d..1e42bd38c 100644 --- a/package.json +++ b/package.json @@ -179,7 +179,7 @@ "chai-bytes": "^0.1.2", "css-loader": "^3.6.0", "dashdash": "1.14.1", - "electron": "^13.1.9", + "electron": "^13.6.2", "electron-builder": "22.8.0", "electron-notarize": "^0.2.0", "eslint": "4.14.0", diff --git a/ts/components/basic/SessionIdEditable.tsx b/ts/components/basic/SessionIdEditable.tsx index b43d8d526..7571ba419 100644 --- a/ts/components/basic/SessionIdEditable.tsx +++ b/ts/components/basic/SessionIdEditable.tsx @@ -11,10 +11,21 @@ type Props = { onPressEnter?: any; maxLength?: number; isGroup?: boolean; + dataTestId?: string; }; export const SessionIdEditable = (props: Props) => { - const { placeholder, onPressEnter, onChange, editable, text, value, maxLength, isGroup } = props; + const { + placeholder, + onPressEnter, + onChange, + editable, + text, + value, + maxLength, + isGroup, + dataTestId, + } = props; const inputRef = useRef(null); useFocusMount(inputRef, editable); @@ -48,6 +59,7 @@ export const SessionIdEditable = (props: Props) => { onBlur={handleChange} value={value || text} maxLength={maxLength} + data-testid={dataTestId} /> ); diff --git a/ts/components/conversation/Timestamp.tsx b/ts/components/conversation/Timestamp.tsx index e277062f8..589593340 100644 --- a/ts/components/conversation/Timestamp.tsx +++ b/ts/components/conversation/Timestamp.tsx @@ -13,8 +13,6 @@ type Props = { isConversationListItem?: boolean; }; -const UPDATE_FREQUENCY = 60 * 1000; - const TimestampContainerListItem = styled.div` flex-shrink: 0; margin-inline-start: 6px; @@ -28,6 +26,8 @@ const TimestampContainerListItem = styled.div` color: var(--color-text); `; +const UPDATE_FREQUENCY = 60 * 1000; + const TimestampContainerNotListItem = styled.div` font-size: 11px; line-height: 16px; diff --git a/ts/components/dialog/SessionSeedModal.tsx b/ts/components/dialog/SessionSeedModal.tsx index 43bafc71d..bba69097a 100644 --- a/ts/components/dialog/SessionSeedModal.tsx +++ b/ts/components/dialog/SessionSeedModal.tsx @@ -107,7 +107,7 @@ const Seed = (props: SeedProps) => {

{i18n('recoveryPhraseSavePromptMain')}

- + {recoveryPhrase} diff --git a/ts/components/leftpane/conversation-list-item/ConversationListItem.tsx b/ts/components/leftpane/conversation-list-item/ConversationListItem.tsx index bbbd100a3..065ae17c4 100644 --- a/ts/components/leftpane/conversation-list-item/ConversationListItem.tsx +++ b/ts/components/leftpane/conversation-list-item/ConversationListItem.tsx @@ -19,7 +19,7 @@ import { useIsPrivate, } from '../../../hooks/useParamSelector'; import { MemoConversationListItemContextMenu } from '../../menu/ConversationListItemContextMenu'; -import { HeaderItem } from './HeaderItem'; +import { ConversationListItemHeaderItem } from './HeaderItem'; import { MessageItem } from './MessageItem'; // tslint:disable-next-line: no-empty-interface @@ -127,7 +127,7 @@ const ConversationListItem = (props: Props) => { >
- +
diff --git a/ts/components/leftpane/conversation-list-item/HeaderItem.tsx b/ts/components/leftpane/conversation-list-item/HeaderItem.tsx index c8e69fc72..a50260e5b 100644 --- a/ts/components/leftpane/conversation-list-item/HeaderItem.tsx +++ b/ts/components/leftpane/conversation-list-item/HeaderItem.tsx @@ -73,7 +73,7 @@ const ListItemIcons = () => { ); }; -export const HeaderItem = () => { +export const ConversationListItemHeaderItem = () => { const conversationId = useContext(ContextConversationId); const convoProps = useHeaderItemProps(conversationId); diff --git a/ts/components/menu/Menu.tsx b/ts/components/menu/Menu.tsx index f148a6b5c..5dafc5445 100644 --- a/ts/components/menu/Menu.tsx +++ b/ts/components/menu/Menu.tsx @@ -196,7 +196,9 @@ export function getDeleteContactMenuItem( if (isPublic) { menuItemText = window.i18n('leaveGroup'); } else { - menuItemText = window.i18n('delete'); + menuItemText = isGroup + ? window.i18n('editMenuDeleteGroup') + : window.i18n('editMenuDeleteContact'); } const onClickClose = () => { diff --git a/ts/components/registration/SignUpTab.tsx b/ts/components/registration/SignUpTab.tsx index 7bbb8f3dd..178104b77 100644 --- a/ts/components/registration/SignUpTab.tsx +++ b/ts/components/registration/SignUpTab.tsx @@ -70,7 +70,7 @@ const SignUpSessionIDShown = (props: { continueSignUp: () => void }) => { {window.i18n('yourUniqueSessionID')} - +
{window.i18n('allUsersAreRandomly...')}
diff --git a/ts/receiver/dataMessage.ts b/ts/receiver/dataMessage.ts index 1be4dafac..739ca67c4 100644 --- a/ts/receiver/dataMessage.ts +++ b/ts/receiver/dataMessage.ts @@ -362,29 +362,28 @@ export async function isMessageDuplicate({ serverTimestamp, }: MessageId) { const { Errors } = window.Signal.Types; - // serverId is only used for opengroupv2 + // serverTimestamp is only used for opengroupv2 try { let result; if (serverTimestamp) { // first try to find a duplicate with the same serverTimestamp from this sender - if (serverTimestamp) { - result = await getMessageBySenderAndServerTimestamp({ - source, - serverTimestamp, - }); - } + + result = await getMessageBySenderAndServerTimestamp({ + source, + serverTimestamp, + }); + // if we have a result, it means a specific user sent two messages either with the same serverTimestamp. // no need to do anything else, those messages must be the same // Note: this test is not based on which conversation the user sent the message // but we consider that a user sending two messages with the same serverTimestamp is unlikely return Boolean(result); - } else { - result = await getMessageBySender({ - source, - sourceDevice, - sentAt: timestamp, - }); } + result = await getMessageBySender({ + source, + sourceDevice, + sentAt: timestamp, + }); if (!result) { return false; diff --git a/ts/receiver/hashDuplicateFilter.ts b/ts/receiver/hashDuplicateFilter.ts deleted file mode 100644 index b7680cc41..000000000 --- a/ts/receiver/hashDuplicateFilter.ts +++ /dev/null @@ -1,48 +0,0 @@ -import _ from 'lodash'; -import { SignalService } from '../protobuf'; -import { sha256 } from '../session/crypto'; - -const recentHashByConvo = new Map>(); - -const maxHashToKeepPerConvo = 10; - -export function isDuplicateBasedOnHash( - dataMessage: SignalService.DataMessage, - conversationId: string, - sender: string -): boolean { - const toUseForHash = { - ..._.omit( - SignalService.DataMessage.toObject(dataMessage), - 'timestamp', - 'profile', - 'preview', - 'profileKey' - ), - conversationId, - sender, - }; - - if (!recentHashByConvo.has(conversationId)) { - recentHashByConvo.set(conversationId, new Array()); - } - const newHash = sha256(JSON.stringify(toUseForHash)); - - // this can only be set based on the .set above() - let recentHashForConvo = recentHashByConvo.get(conversationId) as Array; - - // this hash already exists for this convo - if (recentHashForConvo.some(n => n === newHash)) { - return true; - } - // push the new hash at the end - recentHashForConvo.push(newHash); - if (recentHashForConvo.length > maxHashToKeepPerConvo) { - // slice the last maxHashToKeepPerConvo hashes - recentHashForConvo = recentHashForConvo?.slice(-maxHashToKeepPerConvo); - } - recentHashByConvo.set(conversationId, recentHashForConvo); - return false; -} - -// build a hash of the data and check against recent messages diff --git a/ts/receiver/receiver.ts b/ts/receiver/receiver.ts index abb9c2f93..0e2212ce1 100644 --- a/ts/receiver/receiver.ts +++ b/ts/receiver/receiver.ts @@ -26,7 +26,6 @@ import { OpenGroupRequestCommonType } from '../session/apis/open_group_api/openg import { handleMessageJob } from './queuedJob'; import { fromBase64ToArray } from '../session/utils/String'; import { removeMessagePadding } from '../session/crypto/BufferPadding'; -import { isDuplicateBasedOnHash } from './hashDuplicateFilter'; import { createTaskWithTimeout } from '../session/utils/TaskWithTimeout'; import { perfEnd, perfStart } from '../session/utils/Performance'; @@ -317,7 +316,7 @@ export async function handleOpenGroupV2Message( source: sender, message: dataMessage, }; - // WARNING this is very important that the isMessageDuplicate is made in the conversation.queueJob + // WARNING this is important that the isMessageDuplicate is made in the conversation.queueJob const isDuplicate = await isMessageDuplicate(messageCreationData); if (isDuplicate) { @@ -325,10 +324,6 @@ export async function handleOpenGroupV2Message( return; } - if (isDuplicateBasedOnHash(dataMessage, conversationId, sender)) { - window?.log?.info('Received duplicate message based on hash. Dropping it.'); - return; - } // this line just create an empty message with some basic stuff set. // the whole decoding of data is happening in handleMessageJob() const msg = createMessage(messageCreationData, !isMe); diff --git a/ts/session/apis/open_group_api/opengroupV2/ApiAuth.ts b/ts/session/apis/open_group_api/opengroupV2/ApiAuth.ts index 9226720e2..86a17a2f4 100644 --- a/ts/session/apis/open_group_api/opengroupV2/ApiAuth.ts +++ b/ts/session/apis/open_group_api/opengroupV2/ApiAuth.ts @@ -84,35 +84,6 @@ export async function getAuthToken({ return oneAtATimeGetAuth({ roomId, serverUrl }); } -export type DeleteAuthTokenRequest = OpenGroupRequestCommonType & { token: string }; -export const deleteAuthToken = async ({ - serverUrl, - roomId, - token, -}: DeleteAuthTokenRequest): Promise => { - const request: OpenGroupV2Request = { - method: 'DELETE', - room: roomId, - server: serverUrl, - isAuthRequired: true, - endpoint: 'auth_token', - forcedTokenToUse: token, - }; - try { - const result = await sendApiV2Request(request); - const statusCode = parseStatusCodeFromOnionRequest(result); - if (statusCode !== 200) { - // FIXME not yet sure why this call always return 401 - // window?.log?.warn(`Could not deleteAuthToken, status code: ${statusCode}`); - return; - } - return; - } catch (e) { - window?.log?.error('deleteAuthToken failed:', e); - return; - } -}; - // tslint:disable: member-ordering export async function requestNewAuthToken({ serverUrl, diff --git a/ts/session/apis/open_group_api/opengroupV2/OpenGroupManagerV2.ts b/ts/session/apis/open_group_api/opengroupV2/OpenGroupManagerV2.ts index 3519b0fa7..d2e279d7f 100644 --- a/ts/session/apis/open_group_api/opengroupV2/OpenGroupManagerV2.ts +++ b/ts/session/apis/open_group_api/opengroupV2/OpenGroupManagerV2.ts @@ -14,7 +14,6 @@ import { openGroupV2GetRoomInfo } from './OpenGroupAPIV2'; import { OpenGroupServerPoller } from './OpenGroupServerPoller'; import _ from 'lodash'; -import { deleteAuthToken, DeleteAuthTokenRequest } from './ApiAuth'; import autoBind from 'auto-bind'; let instance: OpenGroupManagerV2 | undefined; @@ -129,13 +128,6 @@ export class OpenGroupManagerV2 { try { const roomConvoId = getOpenGroupV2ConversationId(infos.serverUrl, infos.roomId); if (!allConvos.get(roomConvoId)) { - // leave the group on the remote server - // this request doesn't throw - if (infos.token) { - await deleteAuthToken( - _.pick(infos, 'serverUrl', 'roomId', 'token') as DeleteAuthTokenRequest - ); - } // remove the roomInfos locally for this open group room await removeV2OpenGroupRoom(roomConvoId); getOpenGroupManager().removeRoomFromPolledRooms(infos); diff --git a/ts/session/conversations/ConversationController.ts b/ts/session/conversations/ConversationController.ts index bbcf83f12..e35ce9f96 100644 --- a/ts/session/conversations/ConversationController.ts +++ b/ts/session/conversations/ConversationController.ts @@ -12,10 +12,7 @@ import { actions as conversationActions } from '../../state/ducks/conversations' import { getV2OpenGroupRoom, removeV2OpenGroupRoom } from '../../data/opengroups'; import _ from 'lodash'; import { getOpenGroupManager } from '../apis/open_group_api/opengroupV2/OpenGroupManagerV2'; -import { - deleteAuthToken, - DeleteAuthTokenRequest, -} from '../apis/open_group_api/opengroupV2/ApiAuth'; + import { deleteAllMessagesByConvoIdNoConfirmation } from '../../interactions/conversationInteractions'; let instance: ConversationController | null; @@ -201,12 +198,6 @@ export class ConversationController { window?.log?.info('leaving open group v2', conversation.id); const roomInfos = await getV2OpenGroupRoom(conversation.id); if (roomInfos) { - if (roomInfos.token) { - // leave the group on the remote server - await deleteAuthToken( - _.pick(roomInfos, 'serverUrl', 'roomId', 'token') as DeleteAuthTokenRequest - ); - } getOpenGroupManager().removeRoomFromPolledRooms(roomInfos); // remove the roomInfos locally for this open group room diff --git a/ts/types/LocalizerKeys.ts b/ts/types/LocalizerKeys.ts index 218956f2a..da5b86cbc 100644 --- a/ts/types/LocalizerKeys.ts +++ b/ts/types/LocalizerKeys.ts @@ -214,6 +214,7 @@ export type LocalizerKeys = | 'groupNamePlaceholder' | 'stagedPreviewThumbnail' | 'helpUsTranslateSession' + | 'editMenuDeleteGroup' | 'unreadMessages' | 'documents' | 'audioPermissionNeededTitle' @@ -250,6 +251,7 @@ export type LocalizerKeys = | 'previewThumbnail' | 'photo' | 'setPassword' + | 'editMenuDeleteContact' | 'hideMenuBarTitle' | 'imageCaptionIconAlt' | 'blockAll' diff --git a/yarn.lock b/yarn.lock index 235351d23..381f87435 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3687,10 +3687,10 @@ electron-updater@^4.2.2: pako "^1.0.11" semver "^7.1.3" -electron@^13.1.9: - version "13.1.9" - resolved "https://registry.yarnpkg.com/electron/-/electron-13.1.9.tgz#668e2632b81e9fa21edfd32876282d3e2ff7fd76" - integrity sha512-By4Zb72XNQLrPb70BXdIW3NtEHFwybP5DIQjohnCxOYONq5vojuHjNcTuWnBgMvwQ2qwykk6Tw5EwF2Pt0CWjA== +electron@^13.6.2: + version "13.6.3" + resolved "https://registry.yarnpkg.com/electron/-/electron-13.6.3.tgz#c0217178807d3e0b2175c49dbe33ea8dac447e73" + integrity sha512-kevgR6/RuEhchJQbgCKhHle9HvJhi2dOJlicFZJqbbqa9BVpZARqqFDlwTSatYxmUPUJwu09FvyMwJG2DMQIng== dependencies: "@electron/get" "^1.0.1" "@types/node" "^14.6.2"