Merge remote-tracking branch 'upstream/unstable' into standardised_strings

pull/3206/head
Audric Ackermann 8 months ago
commit d152ce946b

@ -6,10 +6,12 @@ on:
branches:
- clearnet
- unstable
- release/
pull_request:
branches:
- clearnet
- unstable
- release/
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
@ -30,7 +32,11 @@ jobs:
- name: Checkout git repo
uses: actions/checkout@v3
- uses: ./actions/setup_and_build
- name: Setup & Build
uses: ./actions/setup_and_build
- name: Enforce yarn.lock has no duplicates
uses: ./actions/deduplicate_fail
- name: Build windows production binaries
if: runner.os == 'Windows'

@ -6,7 +6,7 @@ on:
branches:
- clearnet
- unstable
- unstable1
- release/
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
@ -28,12 +28,16 @@ jobs:
- name: Checkout git repo
uses: actions/checkout@v3
- uses: ./actions/setup_and_build
- name: Setup & Build
uses: ./actions/setup_and_build
- name: Lint Files
# no need to lint files on all platforms. Just do it once on the quicker one
if: runner.os == 'Linux'
run: yarn lint-full
- name: Enforce yarn.lock has no duplicates
uses: ./actions/deduplicate_fail
- name: Unit Test
run: yarn test

@ -22,7 +22,8 @@ jobs:
- name: Checkout git repo
uses: actions/checkout@v3
- uses: ./actions/setup_and_build
- name: Setup & Build
uses: ./actions/setup_and_build
- name: Build windows production binaries
if: runner.os == 'Windows'

@ -28,14 +28,14 @@
"notificationsSlowModeDescription": "{app_name} will occasionally check for new messages in the background.",
"attachmentsNotification": "{emoji} Attachment",
"notificationsAndroidSystem": "{message_count} new messages in {conversation_count} conversations",
"emojiReactsHoverTwoName": "{name} & {other_name} reacted with <emoji />",
"emojiReactsHoverTwoNameDesktop": "{name} & {other_name} reacted with <emoji/>",
"callsCalledYou": "{name} called you",
"disappearingMessagesLegacy": "{name} is using an outdated client. Disappearing messages may not work as expected.",
"attachmentsMedia": "{name} on {date_time}",
"emojiReactsHoverName": "{name} reacted with <emoji />",
"emojiReactsHoverNameDesktop": "{name} reacted with <emoji/>",
"notificationsIosGroup": "{name} to {conversation_name}",
"emojiReactsHoverTwoNameMultiple": "{name}, {other_name} and {count} others reacted with <emoji />",
"emojiReactsHoverTwoNameOne": "{name}, {other_name} and 1 other reacted with <emoji />",
"emojiReactsHoverTwoNameMultipleDesktop": "{name}, {other_name} and <span>{count} others</span> reacted with <emoji/>",
"emojiReactsHoverTwoNameOneDesktop": "{name}, {other_name} and <span>1 other</span> reacted with <emoji/>",
"disappearingMessagesUpdated": "<b>{admin_name}</b> updated disappearing message settings.",
"groupMemberMoreNew": "<b>{name}</b> and <b>{count} others</b> joined the group.",
"groupMemberLeftMore": "<b>{name}</b> and <b>{count} others</b> left the group.",
@ -169,7 +169,7 @@
"passwordChangeDescription": "Change the password required to unlock {app_name}.",
"nicknameDescription": "Choose a nickname for {name}. This will appear to you in your one-to-one and group conversations.",
"contentDescriptionChooseConversationType": "Choose an action to start a conversation",
"appearanceLanguageDescription": "Choose your language setting for Session. Session will restart when you change your language setting.",
"appearanceLanguageDescription": "Choose your language setting for {app_name}. {app_name} will restart when you change your language setting.",
"appearanceThemesClassicDark": "Classic Dark",
"appearanceThemesClassicLight": "Classic Light",
"clear": "Clear",
@ -668,7 +668,7 @@
"pinUnpinConversation": "Unpin Conversation",
"messageUnread": "Unread messages",
"updateDownloaded": "Update installed, click to restart",
"uploading": "Uploading...",
"uploading": "Uploading",
"useFastMode": "Use Fast Mode",
"recoveryPasswordDescription": "Use your recovery password to load your account on new devices.<br/><br/>Your account cannot be recovered without your recovery password. Make sure it's stored somewhere safe and secure — and don't share it with anyone.",
"banUserBanned": "User banned",
@ -704,9 +704,9 @@
"membersInviteShareDescription": "Would you like to share group message history with <b>{name}</b>?",
"yes": "Yes",
"you": "You",
"emojiReactsHoverYouName": "You & {name} reacted with <emoji />",
"emojiReactsHoverYouNameDesktop": "You & {name} reacted with <emoji/>",
"communityJoinedAlready": "You are already a member of this community.",
"groupOnlyAdmin": "You are the only admin in &lt;b&gt;{group_name}&lt;/b&gt;.&lt;/br&gt;&lt;/br&gt;Group members and settings cannot be changed without an admin.",
"groupOnlyAdmin": "You are the only admin in <b>{group_name}</b>.<br/><br/>Group members and settings cannot be changed without an admin.",
"callsYouCalled": "You called {name}",
"permissionsMicrophoneAccessRequiredDesktop": "You can enable microphone access in {app_name}'s privacy settings",
"callsPermissionsRequiredDescription": "You can enable the \"Voice and Video Calls\" permission in Privacy Settings.",
@ -726,12 +726,12 @@
"callsYouMissedCallPermissions": "You missed a call from <b>{name}</b> because you haven't enabled <b>Voice and Video Calls</b> in Privacy Settings.",
"lockAppEnablePasscode": "You must enable a passcode in your iOS Settings in order to use Screen Lock.",
"settingsRestartDescription": "You must restart {app_name} to apply your new settings.",
"emojiReactsHoverYou": "You reacted with <emoji />",
"emojiReactsHoverYouDesktop": "You reacted with <emoji/>",
"groupRemovedYou": "You were removed from <b>{group_name}</b>.",
"messageRequestPendingDescription": "You will be able to send voice messages and attachments once the recipient has approved this message request.",
"linkPreviewsSendModalDescription": "You will not have full metadata protection when sending link previews.",
"emojiReactsHoverYouNameMultiple": "You, {name} & {count} others reacted with <emoji />",
"emojiReactsHoverYouNameOne": "You, {name} & 1 other reacted with <emoji />",
"emojiReactsHoverYouNameMultipleDesktop": "You, {name} & <span>{count} others</span> reacted with <emoji/>",
"emojiReactsHoverYouNameOneDesktop": "You, {name} & <span>1 other</span> reacted with <emoji/>",
"notificationsFastModeDescriptionIos": "You'll be notified of new messages reliably and immediately using Apple's notification Servers.",
"notificationsFastModeDescriptionAndroid": "You'll be notified of new messages reliably and immediately using Google's notification Servers.",
"accountIdYours": "Your Account ID",
@ -747,5 +747,8 @@
"appearanceZoomIn": "Zoom In",
"appearanceZoomOut": "Zoom Out",
"andMore": "+{count}",
"confirm": "Confirm"
"confirm": "Confirm",
"contentDescriptionQuoteThumbnail": "Thumbnail of image from quoted message",
"attachmentsThisWeek": "This Week",
"attachmentsSendTo": "Send to {name}"
}

@ -0,0 +1,9 @@
name: 'Deduplicate check'
description: 'Deduplicate check'
runs:
using: 'composite'
steps:
- name: Enforce yarn.lock has no duplicates
shell: bash
if: runner.os == 'Linux'
run: yarn dedup-yarn-lock --fail

Binary file not shown.

Before

Width:  |  Height:  |  Size: 318 KiB

After

Width:  |  Height:  |  Size: 388 KiB

@ -2,7 +2,7 @@
"name": "session-desktop",
"productName": "Session",
"description": "Private messaging from your desktop",
"version": "1.12.5",
"version": "1.13.0",
"license": "GPL-3.0",
"author": {
"name": "Oxen Labs",
@ -49,7 +49,7 @@
"protobuf": "pbjs --target static-module --wrap commonjs --out ts/protobuf/compiled.js protos/*.proto && pbts --out ts/protobuf/compiled.d.ts ts/protobuf/compiled.js --force-long",
"sass": "rimraf 'stylesheets/dist/' && webpack --config=./sass.config.js",
"clean": "rimraf 'ts/**/*.js' 'ts/*.js' 'ts/*.js.map' 'ts/**/*.js.map' && rimraf tsconfig.tsbuildinfo;",
"lint-full": "yarn format-full && eslint .",
"lint-full": "yarn dedup-yarn-lock && yarn format-full && eslint .",
"format-full": "prettier --list-different --write \"*.{css,js,json,scss,ts,tsx}\" \"./**/*.{css,js,json,scss,ts,tsx}\"",
"start-prod-test": "cross-env NODE_ENV=production NODE_APP_INSTANCE=$MULTI electron .",
"test": "mocha",
@ -66,11 +66,12 @@
"appImage": "yarn sedtoAppImage; yarn build-release-non-linux; yarn sedtoDeb",
"sedtoAppImage": "sed -i 's/\"target\": \\[\"deb\", \"rpm\", \"freebsd\"\\]/\"target\": \"AppImage\"/g' package.json",
"sedtoDeb": "sed -i 's/\"target\": \"AppImage\"/\"target\": \\[\"deb\", \"rpm\", \"freebsd\"\\]/g' package.json",
"ready": "yarn build-everything && yarn lint-full && yarn test",
"ready": "yarn dedup-yarn-lock --fail && yarn build-everything && yarn lint-full && yarn test",
"postinstall": "yarn patch-package && yarn electron-builder install-app-deps",
"update-git-info": "node ./build/updateLocalConfig.js",
"worker:utils": "webpack --config=./utils.worker.config.js",
"worker:libsession": "rimraf 'ts/webworker/workers/node/libsession/*.node' && webpack --config=./libsession.worker.config.js",
"dedup-yarn-lock": "yarn-deduplicate yarn.lock",
"prepare": "husky install"
},
"dependencies": {
@ -222,7 +223,8 @@
"ts-loader": "^9.4.2",
"typescript": "^5.1.6",
"webpack": "^5.76.3",
"webpack-cli": "^5.1.4"
"webpack-cli": "^5.1.4",
"yarn-deduplicate": "^6.0.2"
},
"engines": {
"node": "18.15.0"

@ -64,13 +64,11 @@ window.setZoomFactor = number => {
// Set the password for the database
window.setPassword = async (passPhrase, oldPhrase) =>
new Promise((resolve, reject) => {
ipc.once('set-password-response', (_event, error) => {
if (error) {
reject(error);
return;
ipc.once('set-password-response', (_event, response) => {
if (!response) {
return reject('window.setPassword: No response from main process');
}
resolve(undefined);
return;
return resolve(response);
});
ipc.send('set-password', passPhrase, oldPhrase);
});

@ -951,7 +951,7 @@
.module-left-pane {
display: inline-flex;
flex-direction: column;
width: 380px;
width: var(--left-panel-width);
height: 100%;
}

@ -184,6 +184,7 @@ label {
box-shadow: var(--modal-drop-shadow);
overflow: hidden;
overflow-y: auto;
display: flex;
flex-direction: column;
@ -382,7 +383,7 @@ label {
}
.session-settings {
width: 100%;
width: var(--main-panel-content-width);
height: 100%;
display: flex;
flex-direction: column;

@ -53,7 +53,7 @@
flex-grow: 1;
display: flex;
flex-direction: column;
max-width: calc(100vw - 380px);
width: var(--main-panel-content-width);
height: 100%;
.selection-mode {

@ -55,7 +55,7 @@ function makeLookup<T>(items: Array<T>, key: string): { [key: string]: T } {
moment.locale(window.getLocale());
const StyledGutter = styled.div`
width: 380px !important;
width: var(--left-panel-width) !important;
transition: none;
`;

@ -57,6 +57,7 @@ export const SessionRadioGroup = (props: Props) => {
}}
beforeMargins={'0 var(--margins-sm) 0 0 '}
radioPosition={radioPosition}
style={{ textAlign: 'start' }}
/>
);
})}

@ -3,6 +3,7 @@ import moment from 'moment';
import useInterval from 'react-use/lib/useInterval';
import useUpdate from 'react-use/lib/useUpdate';
import styled from 'styled-components';
import { CONVERSATION } from '../../session/constants';
type Props = {
timestamp?: number;
@ -39,14 +40,20 @@ export const Timestamp = (props: Props) => {
return null;
}
const momentValue = moment(timestamp);
// this is a hack to make the date string shorter, looks like moment does not have a localized way of doing this for now.
let title = '';
let dateString = '';
const dateString = momentFromNow
? momentValue.fromNow().replace('minutes', 'mins').replace('minute', 'min')
: momentValue.format('lll');
if (timestamp !== CONVERSATION.LAST_JOINED_FALLBACK_TIMESTAMP) {
const momentValue = moment(timestamp);
// this is a hack to make the date string shorter, looks like moment does not have a localized way of doing this for now.
dateString = momentFromNow
? momentValue.fromNow().replace('minutes', 'mins').replace('minute', 'min')
: momentValue.format('lll');
title = moment(timestamp).format('llll');
}
const title = moment(timestamp).format('llll');
if (props.isConversationListItem) {
return <TimestampContainerListItem title={title}>{dateString}</TimestampContainerListItem>;
}

@ -12,7 +12,7 @@ import { SessionWrapperModal } from '../SessionWrapperModal';
import { matchesHash, validatePassword } from '../../util/passwordUtils';
import { assertUnreachable } from '../../types/sqlSharedTypes';
import { matchesHash, validatePassword } from '../../util/passwordUtils';
import { getPasswordHash } from '../../util/storage';
import { getPasswordHash, Storage } from '../../util/storage';
import { SessionWrapperModal } from '../SessionWrapperModal';
import { SessionButton, SessionButtonColor, SessionButtonType } from '../basic/SessionButton';
import { SpacerSM } from '../basic/Text';
@ -197,15 +197,25 @@ export class SessionSetPasswordDialog extends Component<Props, State> {
this.showError();
return;
}
await window.setPassword(enteredPassword, null);
ToastUtils.pushToastSuccess(
'setPasswordSuccessToast',
window.i18n('passwordSet'),
window.i18n('passwordSetDescription')
);
this.props.onOk();
this.closeDialog();
try {
const updatedHash = await window.setPassword(enteredPassword, null);
await Storage.put('passHash', updatedHash);
ToastUtils.pushToastSuccess(
'setPasswordSuccessToast',
window.i18n('passwordSet'),
window.i18n('passwordSetDescription')
);
this.props.onOk();
this.closeDialog();
} catch (err) {
window.log.error(err);
this.setState({
error: window.i18n('setPasswordFail'),
});
this.showError();
}
}
private async handleActionChange(
@ -236,15 +246,25 @@ export class SessionSetPasswordDialog extends Component<Props, State> {
this.showError();
return;
}
await window.setPassword(newPassword, oldPassword);
ToastUtils.pushToastSuccess(
'setPasswordSuccessToast',
window.i18n('passwordChangedDescription')
);
try {
const updatedHash = await window.setPassword(newPassword, oldPassword);
await Storage.put('passHash', updatedHash);
this.props.onOk();
this.closeDialog();
ToastUtils.pushToastSuccess(
'setPasswordSuccessToast',
window.i18n('passwordChangedDescription'),
);
this.props.onOk();
this.closeDialog();
} catch (err) {
window.log.error(err);
this.setState({
error: window.i18n('changePasswordFail'),
});
this.showError();
}
}
private async handleActionRemove(oldPassword: string) {
@ -257,15 +277,25 @@ export class SessionSetPasswordDialog extends Component<Props, State> {
this.showError();
return;
}
await window.setPassword(null, oldPassword);
ToastUtils.pushToastWarning(
'setPasswordSuccessToast',
window.i18n('passwordRemovedDescription')
);
try {
await window.setPassword(null, oldPassword);
await Storage.remove('passHash');
this.props.onOk();
this.closeDialog();
ToastUtils.pushToastWarning(
'setPasswordSuccessToast',
window.i18n('passwordRemovedDescription'),
);
this.props.onOk();
this.closeDialog();
} catch (err) {
window.log.error(err);
this.setState({
error: window.i18n('removePasswordFail'),
});
this.showError();
}
}
private async onEnterPressed(event: any) {

@ -1,26 +1,17 @@
import { useState } from 'react';
import useKey from 'react-use/lib/useKey';
import styled from 'styled-components';
import { getConversationController } from '../../session/conversations';
import { openConversationWithMessages } from '../../state/ducks/conversations';
import { updateUserDetailsModal, UserDetailsModalState } from '../../state/ducks/modalDialog';
import { Avatar, AvatarSize } from '../avatar/Avatar';
import { Flex } from '../basic/Flex';
import { SessionButton, SessionButtonType } from '../basic/SessionButton';
import { SpacerLG } from '../basic/Text';
import { CopyToClipboardButton } from '../buttons/CopyToClipboardButton';
import { SessionInput } from '../inputs';
import { SessionWrapperModal } from '../SessionWrapperModal';
import { ConversationTypeEnum } from '../../models/types';
const StyledInputContainer = styled(Flex)`
textarea {
cursor: default;
overflow: hidden;
top: 14px;
}
`;
import { Flex } from '../basic/Flex';
export const UserDetailsDialog = (props: UserDetailsModalState) => {
const [isEnlargedImageShown, setIsEnlargedImageShown] = useState(false);
@ -79,12 +70,7 @@ export const UserDetailsDialog = (props: UserDetailsModalState) => {
</div>
</div>
<SpacerLG />
<StyledInputContainer
container={true}
width={'100%'}
justifyContent="center"
alignItems="center"
>
<Flex container={true} width={'100%'} justifyContent="center" alignItems="center">
<SessionInput
value={props.conversationId}
textSize="md"
@ -93,7 +79,7 @@ export const UserDetailsDialog = (props: UserDetailsModalState) => {
monospaced={true}
isTextArea={true}
/>
</StyledInputContainer>
</Flex>
<SpacerLG />
<div className="session-modal__button-group__center">
<SessionButton

@ -164,9 +164,9 @@ export const icons: Record<SessionIconType, IconProps> = {
ratio: 1,
},
chatBubble: {
path: 'M6.29289322,16.2928932 C6.4804296,16.1053568 6.73478351,16 7,16 L19,16 C19.5522847,16 20,15.5522847 20,15 L20,5 C20,4.44771525 19.5522847,4 19,4 L5,4 C4.44771525,4 4,4.44771525 4,5 L4,18.5857864 L6.29289322,16.2928932 Z M7.41421356,18 L3.70710678,21.7071068 C3.07714192,22.3370716 2,21.8909049 2,21 L2,5 C2,3.34314575 3.34314575,2 5,2 L19,2 C20.6568542,2 22,3.34314575 22,5 L22,15 C22,16.6568542 20.6568542,18 19,18 L7.41421356,18 Z',
viewBox: '0.5 2 23 20',
ratio: 1,
path: 'M1.27225 19.1234c-.09912 0-.19825-.0141-.289744-.0495-.289745-.1063-.47274-.3682-.47274-.6585V3.5461c0-1.47277 1.288604-2.676471 2.882194-2.676471H17.6276c1.5859 0 2.8822 1.196621 2.8822 2.676471v9.6792c0 1.4727-1.2886 2.6764-2.8822 2.6764H5.02368l-3.20244 3.0164c-.14487.1345-.34312.2124-.54137.2124l-.00762-.0071ZM3.39196 2.28575c-.74724 0-1.35722.56645-1.35722 1.26035v13.1487l2.11971-1.9968c.14487-.1345.33549-.2124.54136-.2124H17.6199c.7473 0 1.3573-.5664 1.3573-1.2603V3.5461c0-.6939-.61-1.26035-1.3573-1.26035H3.38434h.00762Z',
viewBox: '0 0 21 20',
ratio: 21 / 20,
},
check: {
path: 'M0.77,2.61c-0.15-0.15-0.38-0.15-0.53,0c-0.15,0.15-0.15,0.38,0,0.53l1.87,1.87c0.15,0.15,0.38,0.15,0.53,0 l4.12-4.12c0.15-0.15,0.15-0.38,0-0.53c-0.15-0.15-0.38-0.15-0.53,0L2.38,4.22L0.77,2.61z',
@ -174,9 +174,9 @@ export const icons: Record<SessionIconType, IconProps> = {
ratio: 1,
},
checkCircle: {
path: 'M19.9749 38.9783c10.4085 0 19.0017-8.6057 19.0017-19 0-10.40942-8.6082-19.000029-19.0168-19.000029C9.56973.978271.976562 9.56888.976562 19.9783c0 10.3943 8.608258 19 18.998338 19Zm0-3.7427c-8.4659 0-15.24085-6.7908-15.24085-15.2573 0-8.4667 6.75985-15.25728 15.22575-15.25728S35.2342 11.5116 35.2342 19.9783c0 8.4665-6.7934 15.2573-15.2593 15.2573Z M17.9848 28.7219c.66 0 1.2346-.3274 1.6255-.9341l8.2265-12.8509c.2322-.3977.4547-.8255.4547-1.2401 0-.9204-.8152-1.5333-1.6803-1.5333-.5392 0-1.0388.3208-1.428.9271L17.9213 24.758l-3.4181-4.3592c-.4513-.582-.8857-.7622-1.4404-.7622-.8869 0-1.6016.7198-1.6016 1.6218 0 .4444.1721.844.476 1.2432l4.3486 5.2996c.4929.6269 1.0325.9207 1.699.9207Z',
viewBox: '0 0 39 39',
ratio: 1,
path: 'M10.4993 20.8876c5.4783 0 10.0011-4.5294 10.0011-10.0002 0-5.47873-4.5307-10.000193-10.009-10.000193C5.02281.887207.5 5.40867.5 10.8874c0 5.4708 4.53075 10.0002 9.9993 10.0002Zm0-1.9699c-4.4558 0-8.02164-3.5741-8.02164-8.0303 0-4.45621 3.5579-8.03029 8.01374-8.03029 4.4558 0 8.0393 3.57408 8.0393 8.03029 0 4.4562-3.5756 8.0303-8.0314 8.0303Zm-1.04739-3.4283c.34735 0 .64979-.1723.85549-.4916l4.3299-6.76379c.1221-.20931.2393-.4345.2393-.65271 0-.48444-.4291-.80701-.8844-.80701-.2838 0-.5468.16884-.7516.48793L9.41845 13.4031l-1.799-2.2944c-.23756-.3063-.4662-.4011-.75816-.4011-.46679 0-.84296.3788-.84296.8536 0 .2339.09061.4442.25052.6543l2.28881 2.7893c.25943.33.54342.4846.89425.4846Z',
viewBox: '0 0 21 21',
ratio: 21 / 21,
},
chevron: {
path: 'M12,13.5857864 L6.70710678,8.29289322 C6.31658249,7.90236893 5.68341751,7.90236893 5.29289322,8.29289322 C4.90236893,8.68341751 4.90236893,9.31658249 5.29289322,9.70710678 L11.2928932,15.7071068 C11.6834175,16.0976311 12.3165825,16.0976311 12.7071068,15.7071068 L18.7071068,9.70710678 C19.0976311,9.31658249 19.0976311,8.68341751 18.7071068,8.29289322 C18.3165825,7.90236893 17.6834175,7.90236893 17.2928932,8.29289322 L12,13.5857864 Z',
@ -198,9 +198,9 @@ export const icons: Record<SessionIconType, IconProps> = {
ratio: 1,
},
delete: {
path: 'M8.28716 24.5373H18.7049C20.724 24.5373 21.6111 23.5401 21.9231 21.534L23.5096 5.93218L21.6088 6.01432L20.0303 21.4227C19.8884 22.3331 19.4284 22.6989 18.6145 22.6989H8.38546C7.55548 22.6989 7.1036 22.3331 6.96978 21.4227L5.39126 6.01432L3.49037 5.93218L5.07693 21.534C5.38087 23.5482 6.27599 24.5373 8.28716 24.5373ZM3.60064 6.95776H23.4011C24.7332 6.95776 25.5 6.10588 25.5 4.78464V3.35104C25.5 2.03156 24.7332 1.17969 23.4011 1.17969H3.60064C2.32036 1.17969 1.5 2.03156 1.5 3.35104V4.78464C1.5 6.10588 2.27032 6.95776 3.60064 6.95776ZM3.97815 5.20931C3.52823 5.20931 3.33202 5.00521 3.33202 4.55387V3.58181C3.33202 3.13048 3.52823 2.92638 3.97815 2.92638H23.0299C23.4798 2.92638 23.668 3.13048 23.668 3.58181V4.55387C23.668 5.00521 23.4798 5.20931 23.0299 5.20931H3.97815Z',
viewBox: '0 0 26 26',
ratio: 1,
path: 'M6.23797 20.7936h8.68143c1.6826 0 2.4218-.8316 2.6818-2.5046l1.3221-13.01158-1.584.06851-1.3154 12.85017c-.1183.7593-.5016 1.0643-1.1798 1.0643H6.31989c-.69165 0-1.06821-.305-1.17973-1.0643L3.82474 5.34593l-1.58407-.06851L3.5628 18.289c.25327 1.6797.9992 2.5046 2.67517 2.5046ZM2.33255 6.13273H18.8329c1.1101 0 1.7491-.71044 1.7491-1.81233V3.12482c0-1.10041-.639-1.81086-1.7491-1.81086H2.33255c-1.06689 0-1.750519.71045-1.750519 1.81086V4.3204c0 1.10189.641929 1.81233 1.750519 1.81233Zm.3146-1.45817c-.37493 0-.53844-.17021-.53844-.54661v-.81068c0-.37639.16351-.54661.53844-.54661H18.5236c.3749 0 .5317.17022.5317.54661v.81068c0 .3764-.1568.54661-.5317.54661H2.64715Z',
viewBox: '0 0 21 21',
ratio: 21 / 21,
},
deleteModerator: {
path: 'M21.7.7H5.1c-1.2 0-2.2.5-3 1.3C1.3 2.8.9 3.8.9 5v10.5c0 1.1.4 2.2 1.2 3 .8.8 1.8 1.2 2.9 1.2h16.7c1.1 0 2.2-.5 2.9-1.2.8-.8 1.2-1.9 1.2-3V5c0-.6-.1-1.1-.3-1.6-.2-.5-.5-1-.9-1.4-.4-.4-.8-.7-1.4-.9-.4-.3-.9-.4-1.5-.4zm2.1 14.8c0 .6-.2 1.1-.6 1.5-.4.4-.9.6-1.5.6H5.1c-.6 0-1.1-.2-1.5-.6-.4-.4-.6-1-.6-1.5V5c0-.6.2-1.1.6-1.5.4-.4.9-.6 1.5-.6h16.7c.6 0 1.1.2 1.5.6.4.4.6.9.6 1.5-.1 0-.1 10.5-.1 10.5zM14.4 11.3h2.7c.3 0 .5-.1.7-.3.4-.4.4-1.1 0-1.5-.2-.2-.5-.3-.7-.3H9.7c-.3 0-.5.1-.7.3-.4.4-.4 1.1 0 1.5.2.2.5.3.7.3h4.7z',
@ -323,9 +323,9 @@ export const icons: Record<SessionIconType, IconProps> = {
ratio: 1,
},
messageRequest: {
path: 'M2.6 20.47c-.1 0-.2-.02-.29-.05a.7.7 0 0 1-.48-.65V5.16c0-1.45 1.32-2.63 2.95-2.63h14.6c1.63 0 2.96 1.17 2.96 2.63v9.51c0 1.45-1.33 2.63-2.96 2.63H6.46l-3.29 2.96a.85.85 0 0 1-.55.21H2.6ZM4.79 3.92c-.76 0-1.39.56-1.39 1.24v12.92l2.17-1.96c.15-.14.35-.21.56-.21h13.25c.77 0 1.4-.56 1.4-1.24V5.16c0-.68-.63-1.24-1.4-1.24H4.77h.01Z M12.15 6.08c-1.47 0-2.42.69-2.45 2.32h1.34c.07-.9.5-1.13 1.11-1.13.6 0 .91.37.91.8 0 .75-.24.9-1.55 1.74v1.15h1.35v-.98c.76-.37 1.6-.97 1.6-2.06 0-1.08-.8-1.84-2.3-1.84ZM12.94 11.73h-1.55v1.42h1.55v-1.42Z',
viewBox: '0 0 24 23',
ratio: 1.0434782609,
path: 'M1.27225 19.1234c-.09912 0-.19825-.0141-.289744-.0495-.289745-.1063-.47274-.3682-.47274-.6585V3.5461c0-1.47277 1.288604-2.676471 2.882194-2.676471H17.6276c1.5859 0 2.8822 1.196621 2.8822 2.676471v9.6792c0 1.4727-1.2886 2.6764-2.8822 2.6764H5.02368l-3.20244 3.0164c-.14487.1345-.34312.2124-.54137.2124l-.00762-.0071ZM3.39196 2.28575c-.74724 0-1.35722.56645-1.35722 1.26035v13.1487l2.11971-1.9968c.14487-.1345.33549-.2124.54136-.2124H17.6199c.7473 0 1.3573-.5664 1.3573-1.2603V3.5461c0-.6939-.61-1.26035-1.3573-1.26035H3.38434h.00762Zm7.19634 2.06191c-1.61188 0-2.65237.67619-2.68596 2.2829H9.3682c.07836-.88152.5597-1.11672 1.2201-1.11672.6605 0 .9958.3626.9958.79333 0 .73499-.2666.88199-1.70098 1.70518v1.13632h1.47758v-.96972c.8278-.3626 1.759-.95059 1.759-2.01831s-.8752-1.81298-2.5314-1.81298Zm.8614 5.5556H9.74879v1.40094h1.70091V9.90326Z',
viewBox: '0 0 21 20',
ratio: 21 / 20,
},
microphone: {
path: 'M43.362728,18.444286 C46.0752408,18.444286 48.2861946,16.2442453 48.2861946,13.5451212 L48.2861946,6.8991648 C48.2861946,4.20004074 46.0752408,2 43.362728,2 C40.6502153,2 38.4392615,4.20004074 38.4392615,6.8991648 L38.4392615,13.5451212 C38.4392615,16.249338 40.6502153,18.444286 43.362728,18.444286 Z M51.0908304,12.9238134 C51.4388509,12.9238134 51.7203381,13.2039112 51.7203381,13.5502139 C51.7203381,17.9248319 48.3066664,21.5202689 43.9871178,21.8411082 L43.9871178,21.8411082 L43.9871178,25.747199 L47.2574869,25.747199 C47.6055074,25.747199 47.8869946,26.0272968 47.8869946,26.3735995 C47.8869946,26.7199022 47.6055074,27 47.2574869,27 L47.2574869,27 L39.4628512,27 C39.1148307,27 38.8333435,26.7199022 38.8333435,26.3735995 C38.8333435,26.0272968 39.1148307,25.747199 39.4628512,25.747199 L39.4628512,25.747199 L42.7332204,25.747199 L42.7332204,21.8411082 C38.4136717,21.5253616 35,17.9248319 35,13.5502139 C35,13.2039112 35.2814872,12.9238134 35.6295077,12.9238134 C35.9775282,12.9238134 36.2538974,13.2039112 36.2436615,13.5502139 C36.2436615,17.4512121 39.4321435,20.623956 43.3524921,20.623956 C47.2728408,20.623956 50.4613228,17.4512121 50.4613228,13.5502139 C50.4613228,13.2039112 50.7428099,12.9238134 51.0908304,12.9238134 Z M43.362728,3.24770829 C45.3843177,3.24770829 47.0322972,4.88755347 47.0322972,6.8991648 L47.0322972,13.5451212 C47.0322972,15.5567325 45.3843177,17.1965777 43.362728,17.1965777 C41.3411383,17.1965777 39.6931589,15.5567325 39.6931589,13.5451212 L39.6931589,6.8991648 C39.6931589,4.88755347 41.3411383,3.24770829 43.362728,3.24770829',
@ -358,14 +358,14 @@ export const icons: Record<SessionIconType, IconProps> = {
ratio: 4,
},
padlock: {
path: 'M12 12.74a1.4 1.4 0 0 0-.54 2.67v1.52c0 .17.14.31.3.31h.48c.17 0 .3-.14.3-.3V15.4a1.4 1.4 0 0 0-.53-2.67H12Z M17.53 9.43V7.18a5.54 5.54 0 0 0-11.06 0v2.25a3.6 3.6 0 0 0-1.75 3.08v5.24a3.6 3.6 0 0 0 3.6 3.6h7.37a3.6 3.6 0 0 0 3.59-3.6v-5.24c0-1.3-.7-2.45-1.75-3.08ZM8.16 7.18a3.84 3.84 0 0 1 7.67 0v1.7H8.16v-1.7Zm9.43 10.57a1.9 1.9 0 0 1-1.9 1.9H8.3a1.9 1.9 0 0 1-1.9-1.9v-5.24c0-1.05.86-1.9 1.9-1.9h7.38c1.04 0 1.9.85 1.9 1.9v5.24Z',
viewBox: '0 0 24 23',
ratio: 1.0434782609,
path: 'M10.4986 11.2568c-.78025 0-1.41266.6329-1.41266 1.4136 0 .5847.35401 1.0869.86269 1.3035v1.5409c0 .1754.14087.3164.31617.3164h.4743c.1753 0 .3162-.141.3162-.3164v-1.5409c.5053-.2166.8627-.7153.8627-1.3035 0-.7807-.6324-1.4136-1.4126-1.4136h-.0068ZM16.1131 7.90026V5.61651C16.1131 2.52107 13.5938 0 10.497 0 7.40026 0 4.88436 2.52107 4.88436 5.61651v2.28375c-1.06204.63972-1.77694 1.7988-1.77694 3.12644v5.3241C3.10742 18.3629 4.74344 20 6.7541 20h7.4893c2.0106 0 3.6466-1.6371 3.6466-3.6492v-5.3241c0-1.32764-.7149-2.49016-1.7769-3.12644ZM6.60287 5.61651c0-2.14961 1.746-3.89682 3.89413-3.89682 2.1481 0 3.8941 1.74721 3.8941 3.89682V7.3362H6.60287V5.61651ZM16.1715 16.3508c0 1.0628-.8661 1.9295-1.9281 1.9295H6.7541c-1.06204 0-1.92817-.8667-1.92817-1.9295v-5.3241c0-1.06281.86613-1.92954 1.92817-1.92954h7.4893c1.062 0 1.9281.86673 1.9281 1.92954v5.3241Z',
viewBox: '0 0 21 20',
ratio: 21 / 20,
},
paintbrush: {
path: 'M16.32 15.02a.53.53 0 0 1-.38-.16l-7.29-7.3a.54.54 0 0 1-.16-.37c0-.15.06-.28.16-.38l.25-.24.66-.66 1.19-1.18 2.92-2.92c.12-.11.24-.2.35-.26l.1-.07c.1-.07.2-.1.31-.1h.3c.1 0 .2.02.27.07l.06.04c.08.04.2.1.3.2.3.27.52.5.73.72.2.2.3.44.32.7.3.02.57.18.87.48l1.88 1.88c.43.43.53.92.3 1.42.5-.23.98-.14 1.4.29l.2.18.56.57c.12.13.2.26.3.38.02.05.05.1.09.14.07.09.1.2.1.32v.3c0 .12-.03.23-.1.32l-.1.14c-.08.12-.18.26-.3.38l-3.48 3.49-1.35 1.35-.04.06c-.1.12-.24.2-.4.2h-.02ZM9.78 7.19l6.53 6.53 1.07-1.08 3.48-3.48.19-.24c-.07-.1-.14-.2-.2-.26-.17-.19-.35-.36-.53-.54l-.2-.19c-.09-.1-.13-.1-.13-.1s-.05 0-.16.08L18.1 9.07a.94.94 0 0 1-.38.16.53.53 0 0 1-.54-.82l.09-.12.15-.24 1.01-1.5c.12-.18.11-.2-.02-.33l-1.88-1.88a.79.79 0 0 0-.21-.18s-.06.01-.25.1a4.6 4.6 0 0 1-.1.05l-.08.03a.53.53 0 0 1-.58-.11.54.54 0 0 1-.12-.59l.05-.1.09-.22c.05-.11.03-.14-.01-.18a13.78 13.78 0 0 0-.72-.7l-.18.13-2.92 2.91-1.19 1.18-.53.53ZM5.04 21.62h-.57a.53.53 0 0 1-.21-.05 2.8 2.8 0 0 1-2.3-2.21l-.06-.18a.54.54 0 0 1-.02-.15v-.56l.01-.1c.17-.82.52-1.43 1.08-1.86.24-.18.53-.4.83-.6l3.57-2.34c.39-.26.43-.51.42-.73 0-.19-.09-.35-.27-.53l-.35-.35-.95-.95c-.52-.53-.53-1.21 0-1.74l.97-.99.39-.38a.7.7 0 0 1 .1-.09c.2-.17.53-.17.72.03l7.28 7.28c.1.1.16.23.16.37 0 .15-.06.28-.16.38l-.22.21-.55.54-.26.27-.42.4c-.52.52-1.2.51-1.73 0l-1.29-1.3c-.18-.18-.35-.27-.54-.28-.3-.01-.53.12-.73.43l-.03.05c-.77 1.18-1.57 2.4-2.37 3.59a8.5 8.5 0 0 1-.88 1.1c-.34.36-.8.58-1.4.7l-.06.02a.57.57 0 0 1-.16.02Zm-.48-1.06h.4a.72.72 0 0 1 .1-.03c.38-.07.65-.2.82-.38.29-.3.55-.63.78-.97.8-1.18 1.59-2.4 2.36-3.58l.03-.05a1.82 1.82 0 0 1 2.92-.3l1.28 1.28c.1.1.13.1.25 0l.4-.4.27-.27.38-.38-6.53-6.52-.07.07-.98.98c-.1.1-.11.13 0 .25l.95.94.35.35a1.82 1.82 0 0 1-.32 2.9L4.38 16.8l-.77.56a1.9 1.9 0 0 0-.67 1.17v.43l.03.14.1.35c.27.61.72.97 1.39 1.09l.1.02Zm.23-.4h-.01a1.45 1.45 0 0 1 0-2.9h.01c.8.01 1.44.66 1.44 1.45a1.44 1.44 0 0 1-1.44 1.45Zm0-1.83c-.1 0-.2.04-.27.12a.38.38 0 0 0-.11.27c0 .2.17.37.38.38.1-.02.2-.04.27-.12a.38.38 0 0 0 .11-.27c0-.2-.17-.38-.38-.38Z',
viewBox: '0 0 24 23',
ratio: 1.0434782609,
path: 'M14.7682 13.4754c-.1402 0-.2733-.056-.3714-.1541L7.18933 6.11033c-.09811-.09811-.15417-.23476-.15417-.37491 0-.14016.05606-.2733.15767-.37141l.24177-.23826c.21373-.21023.43798-.43098.65872-.65172l1.17029-1.17029c.96009-.96006 1.92359-1.92362 2.88719-2.880175.1156-.115628.2383-.192713.3469-.26279.035-.021023.0736-.04555.1051-.070077.0876-.0630695.1927-.09460425.3013-.09460425h.2979c.0946 0 .1857.02452705.2662.07358105.0211.0105116.0421.0210232.0596.0315352.0806.042046.1927.098108.2943.196216.2874.269797.5151.497548.7218.714784.1892.19972.2944.43799.3189.69026.2943.02103.5571.1787.8584.48003l1.8571 1.85705c.4239.42397.5256.9075.2943 1.40505.4905-.23126.9671-.13665 1.391.28031l.1892.1857c.1892.18571.3785.37141.5572.56412.1156.12264.2067.25579.2873.37141.0315.04555.063.0911.0981.13665.0666.0911.1051.20323.1051.31535v.29783c0 .11563-.0385.22425-.1051.31535-.0316.04555-.0631.0911-.0946.13665-.0841.11913-.1787.25928-.3049.38192-1.1457 1.14926-2.2915 2.29851-3.4372 3.44781l-1.3315 1.3315s-.0386.056-.0456.063c-.0911.1192-.2312.1927-.3819.2032h-.0315ZM8.30706 5.74243 14.7577 12.193l1.0616-1.0616c1.1458-1.1458 2.2916-2.29506 3.4373-3.44433.0596-.05957.1192-.14716.1857-.24177-.0665-.0946-.1331-.1857-.1962-.25578-.1682-.1822-.3469-.35389-.5221-.52908l-.1927-.18921c-.0911-.0911-.1366-.10161-.1366-.10161s-.0456 0-.1577.07708l-1.6959 1.15277c-.0946.06307-.2102.13315-.3784.16118-.2067.03854-.4134-.05256-.5291-.22775-.1156-.17519-.1156-.40294 0-.57814l.0841-.12964c.0491-.07709.1016-.15417.1507-.23126l1.0021-1.48914c.1156-.17169.1051-.19271-.0245-.32586l-1.8571-1.85704c-.1471-.14716-.1997-.17169-.2102-.1752 0 0-.0561.00701-.2453.09811-.0315.01402-.0631.02803-.1051.04555l-.0736.03154c-.1962.08409-.4239.03854-.5746-.11213-.1507-.15066-.1962-.37841-.1156-.57463l.0455-.10511c.0315-.08059.0596-.14717.0911-.21374.0526-.11563.028-.14366-.0105-.1822-.1892-.20322-.4029-.41346-.6727-.66573-.007-.00351-.0211-.01052-.0351-.01752h-.007c-.0701.04555-.1366.08759-.1717.11913-.9635.95655-1.9236 1.92011-2.8872 2.88017L8.84315 5.22035c-.17519.17519-.35389.35389-.52908.52208h-.00701ZM3.61648 20.0032h-.55711c-.05606 0-.11212-.0105-.16468-.028-.00701 0-.04555-.0141-.04906-.0176-.98458-.1857-1.7239-.7708-2.119832-1.6958-.073581-.1717-.119131-.3434-.157674-.4941-.014015-.0595-.031535-.1191-.049054-.1787-.014015-.049-.021023-.0981-.021023-.1471v-.5536c0-.0351 0-.0701.010511-.1052.164682-.8058.511562-1.4015 1.065172-1.829.23826-.1822.52208-.3959.82341-.5956 1.17379-.7744 2.34759-1.5487 3.52488-2.3161.38543-.2523.42747-.5045.42047-.7183-.00701-.1857-.0911-.3469-.2698-.5256l-.34688-.3468c-.31535-.3119-.62719-.62372-.93904-.93907-.51506-.52207-.51857-1.19832-.007-1.71689.32235-.32586.64471-.65172.97056-.97758l.37842-.37842c.03154-.03153.06658-.06307.09811-.08409.21023-.16818.52908-.16818.71829.02453l7.19345 7.19342c.0981.0981.1541.2348.1541.3749 0 .1402-.0595.2733-.1576.3714l-.2138.2103c-.1787.1752-.3609.3503-.5396.529l-.2663.2663c-.1366.1367-.2697.2698-.4064.403-.5221.5045-1.1948.501-1.7134-.0105-.4275-.4205-.8514-.848-1.27189-1.2719-.1857-.1857-.35038-.2733-.53609-.2803-.30483-.0141-.52207.1121-.72179.4169l-.03154.0491c-.76034 1.1668-1.5487 2.3756-2.34058 3.5529-.25928.3854-.55361.7498-.87596 1.0897-.33287.3504-.78487.5746-1.38052.6867l-.05957.0211c-.04905.014-.10161.0245-.15417.0245l-.00701-.0035Zm-.46601-1.0512h.38192c.03854-.014.07358-.021.10862-.028.37141-.0701.6377-.1927.8129-.3784.2803-.2943.53959-.6167.76384-.9496.78837-1.1738 1.57323-2.3756 2.33357-3.5424l.03153-.049c.50456-.7744 1.17029-.9145 1.64331-.8935.452.0175.87244.2172 1.24384.5921.4205.424.841.848 1.2649 1.2649.1086.1087.1332.1087.2453 0 .1331-.1296.2628-.2592.3924-.3889l.2733-.2733c.1262-.1226.2523-.2488.3785-.3679L6.56673 7.4874l-.07358.07358c-.32235.32236-.64471.64121-.96356.96707-.09811.0981-.11212.12263.00701.24176.30834.31185.62018.62369.92852.93203l.34688.34686c.36441.3644.56062.7779.57814 1.2264.02102.4695-.11913 1.1352-.89699 1.6433-1.17729.7673-2.35109 1.5382-3.52138 2.3125-.2733.1822-.53959.382-.76384.5536-.33637.2593-.55011.6272-.66573 1.1563v.4275c.01401.0455.02452.0911.03504.1366.03153.1262.06307.2453.10511.3399.25929.6062.70428.9601 1.363 1.0792.03504.007.06658.014.09461.0245l.01051.0035Zm.22074-.3924h-.007c-.77786-.0035-1.41556-.6412-1.41907-1.4226 0-.3819.14716-.7428.42046-1.0161.2698-.2698.6272-.4205 1.00561-.4205h.00701c.78136.0036 1.41906.6448 1.42257 1.4226 0 .3784-.14716.7393-.42046 1.0126-.27331.2698-.6307.4205-1.00912.4205v.0035Zm0-1.8045c-.09811 0-.18921.0386-.26279.1121-.07358.0736-.11212.1682-.11212.2663 0 .2033.17169.3714.37491.3749.09461-.014.19622-.0385.2698-.1121.07358-.0736.11212-.1682.11212-.2663 0-.1997-.17519-.3749-.37491-.3749h-.00701Z',
viewBox: '0 0 21 20',
ratio: 1,
},
password: {
path: 'M9.7278 28.8456H29.5053C31.306 28.8456 32.3112 27.8778 32.3112 26.076V17.9462L30.4229 19.8328V25.9327C30.4229 26.6759 29.9972 27.1051 29.2471 27.1051H9.9842C9.2342 27.1051 8.8101 26.6759 8.8101 25.9327V17.979C8.8101 17.2273 9.2342 16.8067 9.9842 16.8067H25.5949L27.3432 15.0679H9.7278C7.927 15.0679 6.9219 16.0322 6.9219 17.8374V26.076C6.9219 27.8778 7.927 28.8456 9.7278 28.8456ZM24.2237 22.4341 26.2336 21.5744 34.4571 13.3588 32.9723 11.8878 24.7644 20.1052 23.8579 22.0587C23.7549 22.2756 24.0049 22.5302 24.2237 22.4341ZM35.1866 12.6215 35.8758 11.9244C36.2506 11.5323 36.267 11.0017 35.8956 10.6432L35.6376 10.387C35.3052 10.0579 34.7616 10.1002 34.398 10.4621L33.7139 11.1384 35.1866 12.6215ZM12.3322 23.3685C13.1127 23.3685 13.7469 22.7343 13.7469 21.9521 13.7469 21.1698 13.1127 20.5356 12.3322 20.5356 11.5465 20.5356 10.9141 21.1698 10.9141 21.9521 10.9141 22.7343 11.5465 23.3685 12.3322 23.3685ZM16.5375 23.3685C17.3198 23.3685 17.9539 22.7343 17.9539 21.9521 17.9539 21.1698 17.3198 20.5356 16.5375 20.5356 15.7552 20.5356 15.1211 21.1698 15.1211 21.9521 15.1211 22.7343 15.7552 23.3685 16.5375 23.3685ZM20.7467 23.3685C21.5307 23.3685 22.1631 22.7343 22.1631 21.9521 22.1631 21.1698 21.5307 20.5356 20.7467 20.5356 19.9644 20.5356 19.332 21.1698 19.332 21.9521 19.332 22.7343 19.9644 23.3685 20.7467 23.3685Z',
@ -448,21 +448,21 @@ export const icons: Record<SessionIconType, IconProps> = {
ratio: 1,
},
recoveryPasswordFill: {
path: 'M14.78.73c.45-.21.91-.33 1.39-.33v.02c.47 0 .92.1 1.37.32l1.7.8.65.3 3.07 1.44a3394.44 3394.44 0 0 1 7.36 3.43 3.4 3.4 0 0 1 2 3.45V17.78c0 .68-.01 1.36-.03 2.02a23.75 23.75 0 0 1-.64 4.69l-.02.08-.02.08a32.7 32.7 0 0 1-.87 2.71c-.48 1.23-1.1 2.5-1.9 3.89l-.04.05-.04.06a24.75 24.75 0 0 1-2.79 3.62A20.72 20.72 0 0 1 20.75 39l-.1.06-.09.05-.1.06-.1.05c-.93.43-2.05.92-3.27 1.26l-.03.01h-.02a3.48 3.48 0 0 1-1.78 0c-1.14-.32-2.3-.78-3.45-1.36l-.02-.02h-.02c-3.28-1.72-6-4.28-8.1-7.58l-.09-.11-.1-.18a28.05 28.05 0 0 1-1.72-3.43c-.37-.9-.64-1.78-.9-2.63l-.02-.06-.1-.32-.04-.16-.04-.16-.06-.31-.06-.31-.01-.08c-.14-.7-.28-1.4-.36-2.15-.15-1.24-.15-2.4-.15-3.53V9.87a3.2 3.2 0 0 1 1.87-3.1l3.94-1.84 3.94-1.84 2.38-1.12.1-.05.17-.08.05-.03.31-.14.57-.26a135.73 135.73 0 0 1 1.43-.68Zm3.41 18.12 3.11 1.79c.7.4 1.3 1 1.7 1.72.41.72.63 1.54.63 2.37 0 1.15-.44 2.25-1.22 3.06a4.1 4.1 0 0 1-2.95 1.26h-7.37a3.22 3.22 0 0 1-2.38-1 3.46 3.46 0 0 1-.98-2.45 3.56 3.56 0 0 1 .98-2.45 3.32 3.32 0 0 1 2.38-1h2.11l-3.1-1.79c-.71-.4-1.3-1-1.71-1.71a4.81 4.81 0 0 1-.63-2.38c0-1.14.44-2.24 1.23-3.05a4.1 4.1 0 0 1 2.94-1.27h7.37c.88 0 1.73.36 2.35 1.01a3.52 3.52 0 0 1 0 4.88 3.27 3.27 0 0 1-2.35 1.01h-2.11Zm-7.9-.7c.32.53.77.97 1.3 1.28l4.1 2.35v-3.52c0-.13.04-.25.13-.34.08-.09.2-.14.32-.14h4.16a2.23 2.23 0 0 0 1.66-.74 2.4 2.4 0 0 0 .63-1.76 2.38 2.38 0 0 0-2.36-2.26h-7.22a3.26 3.26 0 0 0-3.21 3.34c.01.63.18 1.24.5 1.78Zm1.87 9.84h7.22c1.77 0 3.26-1.5 3.22-3.34a3.7 3.7 0 0 0-.5-1.79 3.54 3.54 0 0 0-1.3-1.28l-4.09-2.36v3.52a.5.5 0 0 1-.13.34.46.46 0 0 1-.33.14H12.1a2.23 2.23 0 0 0-1.66.74 2.4 2.4 0 0 0-.63 1.76A2.38 2.38 0 0 0 12.16 28Z',
viewBox: '0 0 33 41',
ratio: 1,
path: 'M9.86379.350833c.22691-.110307.46401-.167239.70451-.167239l.0034.007116c.2338 0 .4641.053375.6944.163681.2812.138773.5691.27043.857.402086l.332.153006 1.5615.733007c.5083.23718 1.0167.47495 1.5253.71284l.0001.00004c.735.34382 1.4706.68787 2.2074 1.03068.6943.3238 1.0737.98208 1.0161 1.74711-.0043.04146-.0031.09783-.0016.16139v.00017c.0008.03458.0016.07129.0016.10887.0034.08896.0034.18147.0034.28822-.0101.97141-.0101 1.96061 0 2.93203v.01779l-.0034.01779v.34326c-.0034.34345-.0068.69035-.0169 1.02672-.0169.8931-.1795 1.74-.3218 2.3769l-.0101.0427-.0136.0427c-.1219.4341-.2608.8967-.4403 1.3735-.2405.6262-.5556 1.2703-.9654 1.9713l-.017.0284-.0203.0285c-.4844.7472-.9349 1.3308-1.4159 1.8396-.7892.8327-1.68 1.5159-2.6522 2.0389-.0152.0089-.0313.0187-.0475.0285-.016.0098-.0321.0196-.0473.0285l-.0508.0284-.0509.0249c-.4742.2206-1.0398.4662-1.6597.6405l-.0136.0071h-.0135c-.1491.0392-.3015.057-.4471.057-.1457 0-.2947-.0178-.4539-.0605-.57925-.1601-1.16864-.3914-1.75125-.6868l-.01016-.0106h-.01016c-1.66315-.8754-3.04516-2.1706-4.10876-3.8465l-.04742-.057-.05081-.0889c-.36922-.637-.64697-1.1921-.87392-1.7436-.18584-.4567-.32291-.9031-.45581-1.336l-.00825-.0268-.05081-.1637-.02371-.0818-.01693-.0819c-.01016-.0533-.02032-.1058-.03048-.1583-.01017-.0525-.02033-.105-.03049-.1584l-.00769-.0392c-.06877-.3506-.13955-.7115-.182-1.0923-.07551-.6246-.07504-1.21858-.07459-1.78752l.00007-.13038V5.37157c0-.04766.0004-.09406.00079-.13905.00074-.08603.00143-.16693-.00079-.24169-.0271-.69031.3184-1.27386.94505-1.57632.66721-.31131 1.33358-.62263 1.99995-.93394l.00029-.00013.0006-.00028c.66623-.31125 1.33245-.6225 1.99953-.93374L8.5292.980649l.05081-.024908.08468-.0427.0271-.014233c.0519-.02409.10423-.048631.15684-.073303L8.84864.8255c.09502-.044566.19095-.089556.28688-.133072.07089-.033096.14178-.065891.21258-.098648.1728-.079941.34509-.159654.51569-.242947ZM11.594 9.54645l1.58.90775c.3574.2055.6552.5065.8627.8716.2074.3652.3168.7813.3169 1.2051-.0006.5817-.2237 1.1394-.6203 1.5507-.3966.4113-.9343.6426-1.4952.6433H8.49891c-.2234.0027-.4451-.0406-.65225-.1274-.20716-.0868-.39564-.2154-.55454-.3783-.1589-.1629-.28505-.3568-.37115-.5706-.0861-.2138-.13043-.4432-.13043-.6749 0-.2317.04433-.4611.13043-.675.0861-.2138.21225-.4077.37115-.5706.1589-.1629.34738-.2915.55454-.3783.20715-.0868.42885-.1301.65225-.1274H9.5712l-1.58021-.908c-.35759-.2054-.65568-.50626-.86331-.87142-.20764-.36517-.31726-.78131-.3175-1.20524.00066-.58166.22376-1.13931.62036-1.55061.3966-.4113.93431-.64267 1.49519-.64336h3.73917c.4479 0 .8774.18452 1.1941.51296.3167.32843.4946.7739.4946 1.23838s-.1779.90994-.4946 1.23838c-.3167.32844-.7462.51296-1.1941.51296H11.594Zm-4.00532-.36057c.15952.27347.38526.49891.65479.65392l2.07803 1.1933V9.24646c-.0001-.06417.0243-.12576.0679-.17129.0436-.04553.1029-.07127.1647-.07159h2.1108c.1579-.00015.3142-.03356.4593-.09821.1451-.06465.2761-.15918.3849-.27786.1089-.11869.1934-.25907.2484-.41262.0549-.15355.0793-.31708.0715-.48068-.031-.65021-.571-1.14781-1.1979-1.14781H8.96594c-.89863 0-1.65309.76276-1.63184 1.69447.00728.31953.09505.63153.25458.90501Zm.94405 4.99632h3.66517c.8988 0 1.6533-.7627 1.632-1.6932-.0071-.3198-.0948-.6321-.2544-.9058-.1595-.2737-.3854-.4993-.6552-.6544l-2.0767-1.19326v1.78686c.0001.0319-.006.0634-.0177.0929-.0117.0294-.0289.0561-.0506.0787-.0218.0225-.0475.0404-.0759.0526-.0284.0122-.0588.0185-.0895.0185H8.49891c-.15794.0001-.3142.0336-.45931.0983-.14511.0646-.27605.1592-.38488.2779-.10882.1187-.19327.2591-.24823.4127-.05496.1535-.07928.3171-.07148.4807.03084.6499.57098 1.1475 1.19772 1.1475Z',
viewBox: '0 0 21 21',
ratio: 21 / 21,
clipRule: 'evenodd',
fillRule: 'evenodd',
},
recoveryPasswordOutline: {
path: 'm21.3 20.64-3.11-1.79h2.11c.88 0 1.73-.36 2.35-1a3.52 3.52 0 0 0 0-4.89 3.27 3.27 0 0 0-2.35-1.01h-7.37A4.1 4.1 0 0 0 10 13.22a4.41 4.41 0 0 0-1.23 3.05c0 .84.22 1.66.63 2.38.4.72 1 1.31 1.7 1.71l3.11 1.8h-2.1a3.22 3.22 0 0 0-2.39.99 3.46 3.46 0 0 0-.98 2.45 3.56 3.56 0 0 0 .98 2.46 3.32 3.32 0 0 0 2.38 1h7.37a4.1 4.1 0 0 0 2.95-1.27 4.41 4.41 0 0 0 1.22-3.06c0-.83-.22-1.65-.63-2.37a4.6 4.6 0 0 0-1.7-1.72Zm-9.71-1.21c-.53-.3-.98-.75-1.3-1.29a3.7 3.7 0 0 1-.5-1.78 3.26 3.26 0 0 1 3.22-3.34h7.22a2.38 2.38 0 0 1 2.22 3.2 2.4 2.4 0 0 1-1.25 1.37c-.28.13-.59.2-.9.2h-4.16a.45.45 0 0 0-.32.13.49.49 0 0 0-.14.34v3.52l-4.1-2.35Zm7.79 8.56h-7.22a2.38 2.38 0 0 1-2.22-3.21 2.4 2.4 0 0 1 1.25-1.36c.28-.13.59-.2.9-.2h4.16a.45.45 0 0 0 .33-.14.48.48 0 0 0 .13-.34v-3.52l4.1 2.36c.52.3.97.75 1.28 1.28.32.54.5 1.16.5 1.79a3.26 3.26 0 0 1-3.21 3.34Z M16.15 0c-.48 0-.94.11-1.4.34-.46.23-.95.45-1.43.68l-.87.42-.03.01-.02.02-.17.08-.1.05-2.38 1.14-7.89 3.75A3.27 3.27 0 0 0 0 9.66v8.13c0 1.22-.01 2.5.15 3.85.09.8.23 1.55.37 2.28l.12.63.04.17.04.16.1.33c.27.89.54 1.8.92 2.74.45 1.1 1 2.22 1.72 3.5l.1.18.1.12a21.46 21.46 0 0 0 8.09 7.73h.02l.02.02c1.15.6 2.3 1.06 3.45 1.38a3.35 3.35 0 0 0 1.78 0h.05c1.22-.36 2.33-.85 3.27-1.3l.1-.05.1-.05.19-.12a20.78 20.78 0 0 0 5.22-4.1c.95-1.02 1.84-2.19 2.8-3.7l.03-.05.03-.06c.81-1.4 1.43-2.7 1.9-3.96.36-.96.63-1.88.87-2.76l.03-.08.02-.09c.28-1.28.6-2.98.64-4.77.02-.68.02-1.38.03-2.08V16.96a289.3 289.3 0 0 1 0-5.9V9.96a3.48 3.48 0 0 0-2-3.51l-7.36-3.5-3.08-1.48-.65-.3-1.69-.82c-.45-.22-.9-.33-1.37-.33V0Zm-.02 38.13c-.05 0-.12 0-.22-.03-.97-.27-1.97-.67-2.97-1.18a18.71 18.71 0 0 1-7.07-6.76l-.08-.13-.05-.07a24.85 24.85 0 0 1-1.55-3.14c-.32-.81-.56-1.63-.82-2.5l-.1-.32-.13-.66c-.13-.7-.26-1.36-.34-2.05-.14-1.17-.13-2.3-.13-3.5v-7.31c0-.3.02-.6 0-.94 0-.14-.01-.29.28-.43l7.88-3.75 2.39-1.14.02-.02.03-.01.1-.05.17-.09.88-.41 1.48-.7c.12-.07.2-.07.25-.07.06 0 .14 0 .26.06l1.73.83.64.3 3.08 1.48c2.46 1.17 4.9 2.35 7.36 3.51.43.2.44.45.43.69a7 7 0 0 0 0 .84v7.1l-.03 2.04a22.57 22.57 0 0 1-.57 4.2 34 34 0 0 1-.79 2.5c-.41 1.1-.97 2.27-1.7 3.53a22.66 22.66 0 0 1-2.48 3.3 17.99 17.99 0 0 1-4.55 3.56l-.1.05-.09.06-.06.04c-.84.4-1.84.84-2.88 1.14l-.26.03Z',
viewBox: '0 0 33 41',
ratio: 1,
ratio: 0.80487,
},
speaker: {
path: 'M18.5455 20.7824C18.1251 20.7814 17.7164 20.651 17.3799 20.4105L12.8287 17.2067C12.3111 16.8417 11.6847 16.6444 11.0411 16.6437H5.88206C5.248 16.6428 4.64018 16.4021 4.19184 15.9742C3.74349 15.5463 3.49118 14.9663 3.49023 14.3612V8.62232C3.49118 8.01722 3.74349 7.43716 4.19184 7.00929C4.64018 6.58142 5.248 6.34065 5.88206 6.33975H11.109C11.7532 6.33611 12.3794 6.13652 12.8966 5.76996L17.3657 2.59005C17.6581 2.38176 18.0054 2.25521 18.3689 2.22457C18.7323 2.19392 19.0976 2.2604 19.4237 2.41655C19.7498 2.5727 20.024 2.81237 20.2155 3.10874C20.4071 3.40511 20.5084 3.7465 20.5083 4.09471V18.9024C20.5073 19.4008 20.2995 19.8784 19.9302 20.2308C19.561 20.5831 19.0605 20.7815 18.5383 20.7824H18.5455ZM5.88206 8.0457C5.72181 8.0457 5.56813 8.10646 5.45481 8.21459C5.3415 8.32273 5.27784 8.46939 5.27784 8.62232V14.3612C5.27784 14.5141 5.3415 14.6608 5.45481 14.7689C5.56813 14.877 5.72181 14.9378 5.88206 14.9378H11.0483C12.0711 14.9401 13.0666 15.2532 13.8906 15.8317L18.4418 19.0389C18.4675 19.059 18.4989 19.0713 18.532 19.0744C18.5651 19.0774 18.5984 19.071 18.6277 19.056C18.6584 19.0426 18.6842 19.0209 18.702 18.9936C18.7198 18.9663 18.7288 18.9346 18.7278 18.9024V4.09471C18.7298 4.06239 18.7212 4.03028 18.7033 4.0028C18.6853 3.97531 18.659 3.95378 18.6277 3.94117C18.6002 3.92371 18.5678 3.9144 18.5348 3.9144C18.5017 3.9144 18.4693 3.92371 18.4418 3.94117L13.9692 7.12449C13.1418 7.71064 12.1395 8.02867 11.109 8.03205L5.88206 8.0457Z',
viewBox: '0 0 24 23',
ratio: 1.0434782609,
path: 'M17.5507 19.9997c-.4529-.001-.8932-.1415-1.2556-.4006l-4.903-3.4514c-.5576-.3932-1.2324-.6057-1.92572-.6064h-5.5577c-.68306-.001-1.33784-.2604-1.82083-.7213-.483-.461-.7548-1.0858-.75582-1.7377V6.89998c.00102-.65186.27282-1.27674.75582-1.73768.48299-.46093 1.13777-.72031 1.82083-.72128h5.63088c.69394-.00391 1.36854-.21893 1.92574-.61381L16.2797.401569c.315-.224388.6892-.3607178 1.0807-.39372637.3916-.03300863.785.03860307 1.1363.20681837.3514.168215.6467.426408.8531.745681.2063.319278.3155.687038.3153 1.062158v15.952c-.001.5368-.2249 1.0514-.6227 1.431-.3977.3796-.9369.5933-1.4994.5942h.0077ZM3.90868 6.27881c-.17263 0-.33819.06544-.46026.18194-.12206.11649-.19064.27449-.19064.43923v6.18232c0 .1647.06858.3227.19064.4392.12207.1165.28763.182.46026.182h5.56541c1.10191.0025 2.17431.3398 3.06191.963l4.903 3.455c.0277.0216.0615.0349.0972.0382.0356.0033.0715-.0036.1031-.0198.033-.0144.0608-.0378.0799-.0672.0192-.0294.0289-.0636.0279-.0982V2.0225c.0021-.03482-.0072-.0694-.0265-.09901-.0193-.02961-.0477-.05281-.0813-.0664-.0297-.01881-.0646-.02884-.1002-.02884-.0356 0-.0705.01003-.1001.02884l-4.8182 3.42932c-.8914.63144-1.9711.97404-3.08124.97769l-5.63088.01471Z',
viewBox: '0 0 21 20',
ratio: 21 / 20,
},
star: {
path: 'M9.80779568,8.70262392 C9.66225594,8.99747141 9.38107073,9.20193068 9.05571654,9.24948607 L4.1495,9.9666031 L7.69882113,13.4236419 C7.93469487,13.6533829 8.0423575,13.9845141 7.98669695,14.3090433 L7.14926913,19.1916734 L11.5356371,16.8849265 C11.8270199,16.7316912 12.1751567,16.7316912 12.4665396,16.8849265 L16.8529075,19.1916734 L16.0154797,14.3090433 C15.9598192,13.9845141 16.0674818,13.6533829 16.3033555,13.4236419 L19.8526767,9.9666031 L14.9464601,9.24948607 C14.6211059,9.20193068 14.3399207,8.99747141 14.194381,8.70262392 L12.0010883,4.25925434 L9.80779568,8.70262392 Z M8.24682697,7.3464661 L11.104381,1.55737608 C11.4712164,0.814207972 12.5309603,0.814207972 12.8977957,1.55737608 L15.7553497,7.3464661 L22.1457165,8.28051393 C22.9656312,8.40035674 23.2924147,9.40819801 22.6988211,9.98635811 L18.0756101,14.4893656 L19.166697,20.8509567 C19.3068155,21.6679189 18.4492666,22.2908819 17.7156371,21.9050735 L12.0010883,18.8998497 L6.28653961,21.9050735 C5.55291004,22.2908819 4.69536119,21.6679189 4.83547972,20.8509567 L5.92656655,14.4893656 L1.30335554,9.98635811 C0.709762006,9.40819801 1.03654545,8.40035674 1.85646012,8.28051393 L8.24682697,7.3464661',
@ -487,9 +487,9 @@ export const icons: Record<SessionIconType, IconProps> = {
ratio: 1,
},
question: {
path: 'M4.7 5.34c.43 0 .77-.15 1.04-.46.28-.3.42-.71.42-1.22v-.08a2 2 0 0 0-.15-.78 1.83 1.83 0 0 0-1.05-1.06 2.05 2.05 0 0 0-.84-.18c-.67 0-1.2.21-1.58.62-.39.41-.58.95-.58 1.62v.6H.8v-.68a3.13 3.13 0 0 1 .85-2.27c.28-.3.63-.53 1.05-.71.42-.18.9-.27 1.46-.27.46 0 .9.08 1.29.24a3 3 0 0 1 1.9 2.74v.26a2.87 2.87 0 0 1-.71 1.9c-.23.24-.5.44-.8.59-.3.14-.63.2-.98.2h-.2c-.26 0-.4.15-.4.43v1.03H3.15V6.55c0-.36.11-.65.34-.87.22-.22.5-.34.86-.34h.37ZM2.74 9.68c0-.27.1-.5.28-.68.2-.2.43-.3.7-.3.27 0 .5.1.69.3a.96.96 0 0 1 0 1.39.93.93 0 0 1-.69.27c-.27 0-.5-.09-.7-.28a.98.98 0 0 1-.28-.7ZM4.15.72c-.53 0-.98.09-1.36.25a2.78 2.78 0 0 0-1.56 1.6c-.13.37-.2.75-.2 1.15v.42h.68V3.8c0-.72.21-1.32.64-1.79a2.3 2.3 0 0 1 1.77-.7A2.3 2.3 0 0 1 5.78 2a2.24 2.24 0 0 1 .63 1.59v.08c0 .56-.15 1.03-.48 1.39-.32.36-.73.54-1.22.54h-.37c-.3 0-.52.1-.69.27a.93.93 0 0 0-.26.69V7.6H4v-.78a.7.7 0 0 1 .16-.49c.13-.13.3-.18.48-.18h.2c.32 0 .6-.06.87-.19a2.4 2.4 0 0 0 1.19-1.3c.12-.31.18-.63.18-.96v-.26a2.7 2.7 0 0 0-.82-1.9 2.75 2.75 0 0 0-.93-.6 3.15 3.15 0 0 0-1.2-.23ZM2.59.51A3.97 3.97 0 0 1 5.53.48a3.25 3.25 0 0 1 2.06 2.97v.26a3.12 3.12 0 0 1-.78 2.07 2.9 2.9 0 0 1-.87.64c-.34.16-.7.24-1.1.24h-.19c-.09 0-.1.02-.11.02 0 .01-.03.04-.03.15V8.1H2.89V6.55c0-.41.13-.77.4-1.05.29-.27.64-.4 1.05-.4h.37c.35 0 .62-.13.85-.38.23-.26.35-.6.35-1.06v-.08c0-.25-.04-.48-.13-.69a1.58 1.58 0 0 0-.91-.92h-.01a1.8 1.8 0 0 0-.74-.16 1.8 1.8 0 0 0-1.4.54c-.33.36-.5.83-.5 1.45v.84H.53v-.92a3.38 3.38 0 0 1 .92-2.44c.3-.33.69-.58 1.13-.77Zm1.12 8.44a.7.7 0 0 0-.52.23c-.14.13-.2.3-.2.5s.06.38.2.53c.15.14.32.2.52.2s.37-.06.51-.2a.7.7 0 0 0 .22-.53c0-.2-.07-.36-.21-.5h-.01a.66.66 0 0 0-.5-.23Zm-.87-.13c.24-.24.53-.37.87-.37.34 0 .63.13.87.37s.36.53.36.86c0 .34-.12.64-.36.88s-.53.35-.87.35c-.33 0-.63-.11-.87-.34v-.01a1.23 1.23 0 0 1-.36-.88c0-.33.12-.62.36-.86Z',
viewBox: '0 0 8 11',
ratio: 1,
path: 'M10.7002.887695c-4.16979 0-6.86138 1.944055-6.94825 6.563355h3.79194c.20269-2.53438 1.44783-3.21057 3.15631-3.21057 1.7084 0 2.5757 1.04246 2.5757 2.28081 0 2.1131-.6894 2.53572-4.40001 4.90241v3.2669h3.82231v-2.7879c2.1414-1.0425 4.5503-2.73299 4.5503-5.80269S14.9844.887695 10.7002.887695ZM12.9284 16.8601H8.52841v4.0276h4.39999v-4.0276Z',
viewBox: '0 0 21 21',
ratio: 21 / 21,
},
users: {
path: 'M9.38,2.17c-1.73,0-3.12,1.4-3.12,3.12s1.4,3.12,3.12,3.12s3.12-1.4,3.12-3.12S11.1,2.17,9.38,2.17z M16.93,0.25c2.3,0.59,3.92,2.67,3.92,5.05s-1.61,4.46-3.92,5.05c-0.56,0.14-1.12-0.19-1.27-0.75c-0.14-0.56,0.19-1.12,0.75-1.27 c1.38-0.35,2.35-1.6,2.35-3.03s-0.97-2.67-2.35-3.03c-0.56-0.14-0.9-0.71-0.75-1.27C15.8,0.44,16.37,0.11,16.93,0.25z M9.38,0.08 c2.88,0,5.21,2.33,5.21,5.21s-2.33,5.21-5.21,5.21S4.17,8.17,4.17,5.29C4.17,2.42,6.5,0.08,9.38,0.08z M21.09,12.75 c2.22,0.57,3.8,2.53,3.9,4.81L25,17.79v2.08c0,0.58-0.47,1.04-1.04,1.04c-0.54,0-0.98-0.41-1.04-0.93l-0.01-0.11v-2.08 c0-1.42-0.96-2.67-2.34-3.02c-0.56-0.14-0.89-0.71-0.75-1.27C19.97,12.94,20.54,12.61,21.09,12.75z M13.54,12.58 c2.8,0,5.09,2.21,5.2,4.99v0.22v2.08c0,0.58-0.47,1.04-1.04,1.04c-0.54,0-0.98-0.41-1.04-0.93l-0.01-0.11v-2.08 c0-1.67-1.3-3.03-2.95-3.12h-0.18H5.21c-1.67,0-3.03,1.3-3.12,2.95v0.18v2.08c0,0.58-0.47,1.04-1.04,1.04 c-0.54,0-0.98-0.41-1.04-0.93L0,19.88V17.8c0-2.8,2.21-5.09,4.99-5.2h0.22h8.33V12.58z',

@ -6,6 +6,9 @@ import { ClipRule, FillRule } from './Icons';
export type SessionIconProps = {
iconType: SessionIconType;
/**
* iconSize is usually the height of the icon, we then have a ratio for each icons to calculate the width.
* see sizeIsWidth for how to do the opposite */
iconSize: SessionIconSize | number;
iconColor?: string;
iconRotation?: number;
@ -19,6 +22,8 @@ export type SessionIconProps = {
style?: CSSProperties;
dataTestId?: string;
unreadCount?: number;
/** for some usecases, we want to fix the width of the icon and have the height be calculated from the ratio of the icon */
sizeIsWidth?: boolean;
};
const getIconDimensionFromIconSize = (iconSize: SessionIconSize | number) => {
@ -187,24 +192,28 @@ export const SessionIcon = (props: SessionIconProps) => {
iconPadding,
style,
dataTestId,
sizeIsWidth,
} = props;
let { iconSize, iconRotation } = props;
iconSize = iconSize || 'medium';
iconRotation = iconRotation || 0;
const iconDimensions = getIconDimensionFromIconSize(iconSize);
const calculatedIconSize = getIconDimensionFromIconSize(iconSize);
const iconDef = icons[iconType];
const ratio = iconDef?.ratio || 1;
const ratio = iconDef.ratio;
const fill = iconDef?.fill || undefined;
const clipRule = iconDef?.clipRule || 'nonzero';
const fillRule = iconDef?.fillRule || 'nonzero';
const width = sizeIsWidth ? calculatedIconSize : calculatedIconSize * ratio;
const height = sizeIsWidth ? calculatedIconSize / ratio : calculatedIconSize;
return (
<SessionSvg
viewBox={iconDef.viewBox}
path={iconDef.path}
width={iconDimensions * ratio}
height={iconDimensions}
width={width}
height={height}
rotateDuration={rotateDuration}
glowDuration={glowDuration}
glowStartDelay={glowStartDelay}

@ -91,7 +91,6 @@ const StyledInput = styled(motion.input)<{
`;
export const StyledTextAreaContainer = styled(motion.div)<{
noValue: boolean;
error: boolean;
textSize: TextSizes;
centerText?: boolean;
@ -99,11 +98,12 @@ export const StyledTextAreaContainer = styled(motion.div)<{
}>`
display: flex;
align-items: center;
overflow: hidden;
position: relative;
height: ${props => (props.textSize ? `calc(var(--font-size-${props.textSize}) * 4)` : '48px')};
line-height: 1;
min-height: 80px;
height: 100%;
width: 100%;
margin: var(--margins-sm) var(--margins-md);
padding: 0 var(--margins-md);
background: transparent;
color: ${props => (props.error ? 'var(--danger-color)' : 'var(--input-text-color)')};
@ -111,42 +111,57 @@ export const StyledTextAreaContainer = styled(motion.div)<{
font-family: ${props => (props.monospaced ? 'var(--font-mono)' : 'var(--font-default)')};
${props => `font-size: var(--font-size-${props.textSize});`}
line-height: 1;
${props => props.centerText && 'text-align: center;'}
textarea {
display: flex;
height: 100%;
width: 100%;
padding: 0;
padding: var(--margins-md) 0;
outline: 0;
border: none;
background: transparent;
position: absolute;
top: ${props =>
`calc(var(--font-size-${props.textSize}) + ${props.textSize === 'xl' ? '8px' : '5px'})`};
resize: none;
word-break: break-all;
user-select: all;
${props => props.centerText && 'text-align: center;'}
&:placeholder-shown {
line-height: 1;
font-family: ${props => (props.monospaced ? 'var(--font-mono)' : 'var(--font-default)')};
${props => `font-size: var(--font-size-${props.textSize});`}
line-height: 1;
}
&::placeholder {
color: var(--input-text-placeholder-color);
${props => props.centerText && 'text-align: center;'}
}
}
`;
const StyledPlaceholder = styled(motion.div)<{
error: boolean;
textSize: TextSizes;
editable: boolean;
centerText?: boolean;
monospaced?: boolean;
}>`
position: relative;
width: 100%;
min-height: 80px;
height: 100%;
transition: opacity var(--default-duration) color var(--default-duration);
${props => props.editable && 'cursor: pointer;'}
line-height: 1;
background: transparent;
color: ${props => (props.error ? 'var(--danger-color)' : 'var(--input-text-color)')};
font-family: ${props => (props.monospaced ? 'var(--font-mono)' : 'var(--font-default)')};
font-size: ${props => `var(--font-size-${props.textSize})`};
${props =>
props.centerText &&
'text-align: center; display: flex; align-items: center; justify-content: center;'}
`;
const ErrorItem = (props: { id: string; error: string }) => {
return (
<motion.label
@ -281,6 +296,7 @@ export const SessionInput = (props: Props) => {
const [errorString, setErrorString] = useState('');
const [textErrorStyle, setTextErrorStyle] = useState(false);
const [forceShow, setForceShow] = useState(false);
const [isFocused, setIsFocused] = useState(false);
const textAreaRef = useRef(inputRef?.current || null);
@ -309,7 +325,6 @@ export const SessionInput = (props: Props) => {
}
};
// TODO[epic=ses-893] Type inputProps properly
const inputProps: any = {
id,
type: correctType,
@ -329,6 +344,9 @@ export const SessionInput = (props: Props) => {
onBlur: (event: ChangeEvent<HTMLInputElement>) => {
if (editable && !disableOnBlurEvent) {
updateInputValue(event);
if (isEmpty(value) && isFocused) {
setIsFocused(false);
}
}
},
onKeyDown: (event: KeyboardEvent) => {
@ -386,11 +404,29 @@ export const SessionInput = (props: Props) => {
>
{isTextArea ? (
<StyledTextAreaContainer {...containerProps}>
<textarea
{...inputProps}
ref={inputRef || textAreaRef}
aria-label={ariaLabel || 'session input text area'}
/>
{isFocused ? (
<textarea
{...inputProps}
placeholder={''}
ref={inputRef || textAreaRef}
aria-label={ariaLabel || 'session input text area'}
/>
) : (
<StyledPlaceholder
error={textErrorStyle}
textSize={textSize}
editable={editable}
centerText={centerText}
monospaced={monospaced}
onClick={() => {
if (editable) {
setIsFocused(true);
}
}}
>
{editable ? placeholder : value}
</StyledPlaceholder>
)}
</StyledTextAreaContainer>
) : (
<StyledInput

@ -1,7 +1,7 @@
import styled from 'styled-components';
export const LeftPaneSectionContainer = styled.div`
width: 80px;
width: var(--actions-panel-width);
display: flex;
flex-direction: column;
align-items: center;

@ -1,5 +1,5 @@
import { useDispatch, useSelector } from 'react-redux';
import styled, { CSSProperties } from 'styled-components';
import styled from 'styled-components';
import { resetConversationExternal } from '../../state/ducks/conversations';
import { updateDeleteAccountModal } from '../../state/ducks/modalDialog';
@ -13,7 +13,7 @@ import { getFocusedSettingsSection } from '../../state/selectors/section';
import { useHideRecoveryPasswordEnabled } from '../../state/selectors/settings';
import type { SessionSettingCategory } from '../../types/ReduxTypes';
import { Flex } from '../basic/Flex';
import { SessionIcon, SessionIconSize, SessionIconType } from '../icon';
import { SessionIcon, SessionIconType } from '../icon';
import { LeftPaneSectionHeader } from './LeftPaneSectionHeader';
const StyledSettingsSectionTitle = styled.span`
@ -39,7 +39,7 @@ const StyledSettingsListItem = styled(Flex)<{ active: boolean }>`
`;
const StyledIconContainer = styled.div`
width: 34px;
width: 38px;
`;
type Categories = {
@ -47,58 +47,58 @@ type Categories = {
title: string;
icon: {
type: SessionIconType;
size?: SessionIconSize | number;
size: number;
color?: string;
style?: CSSProperties;
};
};
const getCategories = (): Array<Categories> => {
const forcedSize = { size: 19 };
return [
{
id: 'privacy' as const,
title: window.i18n('sessionPrivacy'),
icon: { type: 'padlock', style: { marginTop: '-5px' } },
icon: { type: 'padlock', ...forcedSize },
},
{
id: 'notifications' as const,
title: window.i18n('sessionNotifications'),
icon: { type: 'speaker' },
icon: { type: 'speaker', ...forcedSize },
},
{
id: 'conversations' as const,
title: window.i18n('sessionConversations'),
icon: { type: 'chatBubble' },
icon: { type: 'chatBubble', ...forcedSize },
},
{
id: 'messageRequests' as const,
title: window.i18n('openMessageRequestInbox'),
icon: { type: 'messageRequest' },
icon: { type: 'messageRequest', ...forcedSize },
},
{
id: 'appearance' as const,
title: window.i18n('sessionAppearance'),
icon: { type: 'paintbrush' },
icon: { type: 'paintbrush', ...forcedSize },
},
{
id: 'permissions' as const,
id: 'permissions',
title: window.i18n('sessionPermissions'),
icon: { type: 'checkCircle', size: 19 },
icon: { type: 'checkCircle', ...forcedSize },
},
{
id: 'help' as const,
title: window.i18n('sessionHelp'),
icon: { type: 'question', size: 19 },
icon: { type: 'question', ...forcedSize },
},
{
id: 'recoveryPassword' as const,
title: window.i18n('sessionRecoveryPassword'),
icon: { type: 'recoveryPasswordFill', size: 'medium' },
icon: { type: 'recoveryPasswordFill', ...forcedSize },
},
{
id: 'clearData' as const,
title: window.i18n('sessionClearData'),
icon: { type: 'delete', size: 19, color: 'var(--danger-color)' },
icon: { type: 'delete', ...forcedSize, color: 'var(--danger-color)' },
},
];
};
@ -143,9 +143,9 @@ const LeftPaneSettingsCategoryRow = (props: { item: Categories }) => {
<StyledIconContainer>
<SessionIcon
iconType={icon.type}
iconSize={icon.size || 23}
iconSize={icon.size}
sizeIsWidth={true}
iconColor={icon.color || 'var(--text-primary-color)'}
style={icon.style}
/>
</StyledIconContainer>
<StyledSettingsSectionTitle style={{ color: isClearData ? 'var(--danger-color)' : 'unset' }}>

@ -58,7 +58,7 @@ const NoContacts = () => {
};
/**
* Makes some validity check and return true if the group was indead created
* Makes some validity check and return true if the group was indeed created
*/
async function createClosedGroupWithErrorHandling(
groupName: string,
@ -77,13 +77,14 @@ async function createClosedGroupWithErrorHandling(
return false;
}
// >= because we add ourself as a member AFTER this. so a 10 group is already invalid as it will be 11 with ourself
// >= because we add ourself as a member AFTER this. so a 10 group is already invalid as it will be 11 when we are included
// the same is valid with groups count < 1
if (groupMemberIds.length < 1) {
onError(window.i18n('groupCreateErrorNoMembers'));
return false;
}
if (groupMemberIds.length >= VALIDATION.CLOSED_GROUP_SIZE_LIMIT) {
onError(window.i18n('groupAddMemberMaximum'));
return false;

@ -62,7 +62,8 @@ export const OverlayCommunity = () => {
return;
}
setGroupUrlError(undefined);
await joinOpenGroup(completeUrl || groupUrl, setGroupUrlError, joinSogsUICallback);
const url = (completeUrl && completeUrl.trim()) || (groupUrl && groupUrl.trim());
await joinOpenGroup(url, setGroupUrlError, joinSogsUICallback);
} catch (e) {
setGroupUrlError(e.message);
window.log.warn(e);

@ -55,11 +55,9 @@ const StyledButtonerContainer = styled.div`
const StyledInputContainer = styled(Flex)`
${StyledTextAreaContainer} {
margin: var(--margins-sm);
textarea {
cursor: default;
overflow: hidden;
top: 12px;
padding: 0;
div:first-child {
padding: 0 var(--margins-sm);
}
}
`;

@ -71,6 +71,7 @@ export const OverlayChooseAction = () => {
title={window.i18n('newMessage')}
ariaLabel={'New message button'}
iconType={'chatBubble'}
iconSize={20}
onClick={openNewMessage}
dataTestId="chooser-new-conversation-button"
/>
@ -78,7 +79,7 @@ export const OverlayChooseAction = () => {
title={window.i18n('createGroup')}
ariaLabel={'Create a group button'}
iconType={'group'}
iconSize={36}
iconSize={30}
onClick={openCreateGroup}
dataTestId="chooser-new-group"
/>
@ -86,6 +87,7 @@ export const OverlayChooseAction = () => {
title={window.i18n('joinOpenGroup')}
ariaLabel={'Join a community button'}
iconType={'communities'}
iconSize={20}
onClick={openJoinCommunity}
dataTestId="chooser-new-community"
/>
@ -93,6 +95,7 @@ export const OverlayChooseAction = () => {
title={window.i18n('sessionInviteAFriend')}
ariaLabel={'Invite a friend button'}
iconType={'addUser'}
iconSize={20}
onClick={inviteAFriend}
dataTestId="chooser-invite-friend"
/>

@ -183,9 +183,12 @@ export const RestoreAccount = () => {
try {
const validName = await ProfileManager.updateOurProfileDisplayName(displayName, true);
const trimmedPassword = recoveryPassword.trim();
setRecoveryPassword(trimmedPassword);
await signInWithNewDisplayName({
displayName: validName,
recoveryPassword,
recoveryPassword: trimmedPassword,
dispatch,
});
} catch (err) {

@ -63,7 +63,6 @@ const BlockedEntries = (props: {
onSelect={addToSelected}
onUnselect={removeFromSelected}
disableBg={true}
maxNameWidth={'33vw'}
/>
);
})}

@ -115,6 +115,7 @@ export const SettingsCategoryPrivacy = (props: {
description={window.i18n('passwordDescription')}
onClick={() => {
displayPasswordModal('set', props.onPasswordUpdated);
forceUpdate();
}}
buttonText={window.i18n('passwordSet')}
dataTestId={'set-password-button'}
@ -128,6 +129,7 @@ export const SettingsCategoryPrivacy = (props: {
description={window.i18n('passwordChangeDescription')}
onClick={() => {
displayPasswordModal('change', props.onPasswordUpdated);
forceUpdate();
}}
buttonText={window.i18n('passwordChange')}
dataTestId="change-password-settings-button"
@ -136,6 +138,7 @@ export const SettingsCategoryPrivacy = (props: {
description={window.i18n('passwordRemoveDescription')}
onClick={() => {
displayPasswordModal('remove', props.onPasswordUpdated);
forceUpdate();
}}
buttonColor={SessionButtonColor.Danger}
buttonText={window.i18n('passwordRemove')}

@ -23,7 +23,11 @@ import { SessionHtmlRenderer } from '../../basic/SessionHTMLRenderer';
import { SpacerMD, SpacerSM } from '../../basic/Text';
import { CopyToClipboardIcon } from '../../buttons/CopyToClipboardButton';
import { SessionIconButton } from '../../icon';
import { SessionSettingButtonItem, SessionSettingsItemWrapper } from '../SessionSettingListItem';
import {
SessionSettingButtonItem,
SessionSettingsItemWrapper,
StyledSettingItem,
} from '../SessionSettingListItem';
import { useHotkey } from '../../../hooks/useHotkey';
import { getIsModalVisble } from '../../../state/selectors/modal';
@ -37,6 +41,12 @@ const StyledSettingsItemContainer = styled.div`
button[data-testid='hide-recovery-password-button'] {
width: 130px;
}
${StyledSettingItem} {
svg {
margin-top: -2px;
}
}
`;
const StyledRecoveryPassword = styled(AnimatedFlex)<{ color: string }>`
@ -113,7 +123,7 @@ export const SettingsCategoryRecoveryPassword = () => {
title={window.i18n('sessionRecoveryPassword')}
icon={{
iconType: 'recoveryPasswordFill',
iconSize: 16,
iconSize: 18,
iconColor: 'var(--text-primary-color)',
}}
description={

@ -1064,13 +1064,15 @@ ipc.on('set-password', async (event, passPhrase, oldPhrase) => {
sqlNode.setSQLPassword(defaultKey);
sqlNode.removePasswordHash();
userConfig.set('dbHasPassword', false);
sendResponse(undefined);
} else {
sqlNode.setSQLPassword(passPhrase);
const newHash = PasswordUtil.generateHash(passPhrase);
sqlNode.savePasswordHash(newHash);
const updatedHash = sqlNode.getPasswordHash();
userConfig.set('dbHasPassword', true);
sendResponse(updatedHash);
}
sendResponse(undefined);
} catch (e) {
const localisedError = locale.messages.passwordFailed;
sendResponse(localisedError || 'Failed to set password');

@ -253,6 +253,7 @@ function getPasswordHash() {
const item = getItemById(PASS_HASH_ID);
return item && item.value;
}
function savePasswordHash(hash: string) {
if (isEmpty(hash)) {
removePasswordHash();
@ -262,6 +263,7 @@ function savePasswordHash(hash: string) {
const data = { id: PASS_HASH_ID, value: hash };
createOrUpdateItem(data);
}
function removePasswordHash() {
removeItemById(PASS_HASH_ID);
}

@ -52,6 +52,7 @@ import { HexKeyPair } from './keypairs';
import { queueAllCachedFromSource } from './receiver';
import { EnvelopePlus } from './types';
import { ConversationTypeEnum, CONVERSATION_PRIORITIES } from '../models/types';
import { CONVERSATION } from '../session/constants';
function groupByNamespace(incomingConfigs: Array<RetrieveMessageItemWithNamespace>) {
const groupedByVariant: Map<
@ -603,7 +604,10 @@ async function handleLegacyGroupUpdate(latestEnvelopeTimestamp: number) {
const members = fromWrapper.members.map(m => m.pubkeyHex);
const admins = fromWrapper.members.filter(m => m.isAdmin).map(m => m.pubkeyHex);
const creationTimestamp = fromWrapper.joinedAtSeconds ? fromWrapper.joinedAtSeconds * 1000 : 0;
const creationTimestamp = fromWrapper.joinedAtSeconds
? fromWrapper.joinedAtSeconds * 1000
: CONVERSATION.LAST_JOINED_FALLBACK_TIMESTAMP;
// then for all the existing legacy group in the wrapper, we need to override the field of what we have in the DB with what is in the wrapper
// We only set group admins on group creation
const groupDetails: ClosedGroup.GroupInfo = {
@ -643,13 +647,12 @@ async function handleLegacyGroupUpdate(latestEnvelopeTimestamp: number) {
const existingTimestampMs = legacyGroupConvo.get('lastJoinedTimestamp');
const existingJoinedAtSeconds = Math.floor(existingTimestampMs / 1000);
if (existingJoinedAtSeconds !== fromWrapper.joinedAtSeconds) {
if (existingJoinedAtSeconds !== creationTimestamp) {
legacyGroupConvo.set({
lastJoinedTimestamp: fromWrapper.joinedAtSeconds * 1000,
lastJoinedTimestamp: creationTimestamp,
});
changes = true;
}
// start polling for this group if we haven't left it yet. The wrapper does not store this info for legacy group so we check from the DB entry instead
if (!legacyGroupConvo.get('isKickedFromGroup') && !legacyGroupConvo.get('left')) {
getSwarmPollingInstance().addGroupId(PubKey.cast(fromWrapper.pubkeyHex));

@ -306,8 +306,12 @@ async function shouldDropIncomingPrivateMessage(
envelope: EnvelopePlus,
content: SignalService.Content
) {
const isUs = UserUtils.isUsFromCache(envelope.source);
// sentAtMoreRecentThanWrapper is going to be true, if the latest contact wrapper we processed was roughly more recent that this message timestamp
const moreRecentOrNah = await sentAtMoreRecentThanWrapper(sentAtTimestamp, 'ContactsConfig');
const moreRecentOrNah = await sentAtMoreRecentThanWrapper(
sentAtTimestamp,
isUs ? 'UserConfig' : 'ContactsConfig'
);
const isSyncedMessage = isUsFromCache(envelope.source);
if (moreRecentOrNah === 'wrapper_more_recent') {
@ -319,30 +323,50 @@ async function shouldDropIncomingPrivateMessage(
? content.dataMessage?.syncTarget || undefined
: envelope.source;
// handle the `us` case first, as we will never find ourselves in the contacts wrapper. The NTS details are in the UserProfile wrapper.
if (isUs) {
const us = getConversationController().get(envelope.source);
const ourPriority = us?.get('priority') || CONVERSATION_PRIORITIES.default;
if (us && ourPriority <= CONVERSATION_PRIORITIES.hidden) {
// if the wrapper data is more recent than this message and the NTS conversation is hidden, just drop this incoming message to avoid showing the NTS conversation again.
window.log.info(
`shouldDropIncomingPrivateMessage: received message in NTS which appears to be hidden in our most recent libsession userconfig, sentAt: ${sentAtTimestamp}. Dropping it`
);
return true;
}
window.log.info(
`shouldDropIncomingPrivateMessage: received message on conversation ${syncTargetOrSource} which appears to NOT be hidden/removed in our most recent libsession userconfig, sentAt: ${sentAtTimestamp}. `
);
return false;
}
if (!syncTargetOrSource) {
return false;
}
const privateConvoInWrapper = await ContactsWrapperActions.get(syncTargetOrSource);
if (
!privateConvoInWrapper ||
privateConvoInWrapper.priority <= CONVERSATION_PRIORITIES.hidden
) {
// the wrapper is more recent that this message and there is no such private conversation. Just drop this incoming message.
if (syncTargetOrSource.startsWith('05')) {
const privateConvoInWrapper = await ContactsWrapperActions.get(syncTargetOrSource);
if (
!privateConvoInWrapper ||
privateConvoInWrapper.priority <= CONVERSATION_PRIORITIES.hidden
) {
// the wrapper is more recent that this message and there is no such private conversation. Just drop this incoming message.
window.log.info(
`shouldDropIncomingPrivateMessage: received message on conversation ${syncTargetOrSource} which appears to be hidden/removed in our most recent libsession contactconfig, sentAt: ${sentAtTimestamp}. Dropping it`
);
return true;
}
window.log.info(
`shouldDropIncomingPrivateMessage: received message on conversation ${syncTargetOrSource} which appears to NOT be hidden/removed in our most recent libsession contactconfig, sentAt: ${sentAtTimestamp}. `
);
} else {
window.log.info(
`received message on conversation ${syncTargetOrSource} which appears to be hidden/removed in our most recent libsession contactconfig, sentAt: ${sentAtTimestamp}. Dropping it`
`shouldDropIncomingPrivateMessage: received message on conversation ${syncTargetOrSource} but neither NTS not 05. Probably nothing to do but let it through. `
);
return true;
}
window.log.info(
`received message on conversation ${syncTargetOrSource} which appears to NOT be hidden/removed in our most recent libsession contactconfig, sentAt: ${sentAtTimestamp}. `
);
} catch (e) {
window.log.warn(
'ContactsWrapperActions.get in handleSwarmDataMessage failed with',
e.message
);
window.log.warn('shouldDropIncomingPrivateMessage: failed with', e.message);
}
}
return false;

@ -62,6 +62,8 @@ export const CONVERSATION = {
MAX_VOICE_MESSAGE_DURATION: 300,
MAX_CONVO_UNREAD_COUNT: 999,
MAX_GLOBAL_UNREAD_COUNT: 99, // the global one does not look good with 4 digits (999+) so we have a smaller one for it
/** NOTE some existing groups might not have joinedAtSeconds and we need a fallback value that is not falsy in order to poll and show up in the conversations list */
LAST_JOINED_FALLBACK_TIMESTAMP: 1,
} as const;
/**

@ -20,6 +20,15 @@ export class NotEnoughWordsError extends MnemonicError {
}
}
/** NOTE 2024-08-07 (Will) Maximum number of words is 13 */
export class TooManyWordsError extends MnemonicError {
constructor(message = "You've entered too many words, please try again") {
super(message);
// restore prototype chain
Object.setPrototypeOf(this, TooManyWordsError.prototype);
}
}
export class InvalidWordsError extends MnemonicError {
constructor(message = "You've entered too few words, please try again") {
super(message);
@ -103,6 +112,10 @@ export function mnDecode(str: string, wordsetName: string = MN_DEFAULT_WORDSET):
if (wlist.length < 12) {
throw new NotEnoughWordsError();
}
if (wlist.length > 13) {
throw new TooManyWordsError();
}
if (
(wordset.prefixLen === 0 && wlist.length % 3 !== 0) ||
(wordset.prefixLen > 0 && wlist.length % 3 === 2)

@ -1,23 +1,22 @@
/* eslint-disable import/no-mutable-exports */
/* eslint-disable no-await-in-loop */
import _, { compact, isFinite, isNumber, sample } from 'lodash';
import _, { compact, sample } from 'lodash';
import pRetry from 'p-retry';
// eslint-disable-next-line import/no-named-default
import { default as insecureNodeFetch } from 'node-fetch';
import semver from 'semver';
import { OnionPaths } from '.';
import { Data } from '../../data/data';
import * as SnodePool from '../apis/snode_api/snodePool';
import { UserUtils } from '../utils';
import { allowOnlyOneAtATime } from '../utils/Promise';
import { ed25519Str } from '../utils/String';
import { DURATION } from '../constants';
import { Snode } from '../../data/types';
import { updateOnionPaths } from '../../state/ducks/onion';
import { Onions, snodeHttpsAgent } from '../apis/snode_api/onions';
import { APPLICATION_JSON } from '../../types/MIME';
import { Onions, snodeHttpsAgent } from '../apis/snode_api/onions';
import { ERROR_CODE_NO_CONNECT } from '../apis/snode_api/SNodeAPI';
import { OnionPaths } from '.';
import * as SnodePool from '../apis/snode_api/snodePool';
import { DURATION } from '../constants';
import { UserUtils } from '../utils';
import { allowOnlyOneAtATime } from '../utils/Promise';
import { ed25519Str } from '../utils/String';
const desiredGuardCount = 3;
const minimumGuardCount = 2;
@ -545,29 +544,7 @@ async function buildNewOnionPathsWorker() {
}
export function getRandomEdgeSnode(snodes: Array<Snode>) {
const allSnodesWithv280 = snodes.filter(snode => {
const snodeStorageVersion = snode.storage_server_version;
if (
!snodeStorageVersion ||
!Array.isArray(snodeStorageVersion) ||
snodeStorageVersion.length !== 3 ||
snodeStorageVersion.some(m => !isNumber(m) || !isFinite(m))
) {
return false;
}
const storageVersionAsString = `${snodeStorageVersion[0]}.${snodeStorageVersion[1]}.${snodeStorageVersion[2]}`;
const verifiedStorageVersion = semver.valid(storageVersionAsString);
if (!verifiedStorageVersion) {
return false;
}
if (semver.lt(verifiedStorageVersion, '2.8.0')) {
return false;
}
return true;
});
const randomEdgeSnode = sample(allSnodesWithv280);
const randomEdgeSnode = sample(snodes);
if (!randomEdgeSnode) {
throw new Error('did not find a single snode which can be the edge');
}

@ -21,6 +21,7 @@ import {
PersistedJob,
RunJobResult,
} from '../PersistedJob';
import { DURATION } from '../../../constants';
const defaultMsBetweenRetries = 15000; // a long time between retries, to avoid running multiple jobs at the same time, when one was postponed at the same time as one already planned (5s)
const defaultMaxAttempts = 2;
@ -55,6 +56,8 @@ async function retrieveSingleDestinationChanges(
return { messages: outgoingConfResults, allOldHashes: compactedHashes };
}
let firstJobStart: number | undefined;
/**
* This function is run once we get the results from the multiple batch-send.
*/
@ -191,6 +194,18 @@ class ConfigurationSyncJob extends PersistedJob<ConfigurationSyncPersistedData>
return RunJobResult.Success;
}
const singleDestChanges = await retrieveSingleDestinationChanges(thisJobDestination);
if (!firstJobStart) {
firstJobStart = Date.now();
}
// not ideal, but we need to postpone the first sync job to after we've handled the incoming config messages
// otherwise we are pushing an incomplete config to the network, which will need to be merged and that action alone
// will bump the timestamp of the config.
// We rely on the timestamp of configs to know when to drop messages that would unhide/unremove a conversation.
// The whole thing is a dirty fix of a dirty fix, that will **eventually** need proper fixing
if (Date.now() - firstJobStart <= 20 * DURATION.SECONDS) {
return RunJobResult.RetryJobIfPossible;
}
// If there are no pending changes then the job can just complete (next time something
// is updated we want to try and run immediately so don't scuedule another run in this case)

@ -113,65 +113,12 @@ describe('OnionPaths', () => {
});
describe('getRandomEdgeSnode', () => {
it('find single valid snode in poll of many non valid snodes', () => {
const originalSnodePool = generateFakeSnodes(20);
const firstValidSnodePool = originalSnodePool.map((m, i) => {
if (i > 0) {
return {
...m,
storage_server_version: [2, 7, 0],
};
}
return m;
});
expect(OnionPaths.getRandomEdgeSnode(firstValidSnodePool)).to.be.deep.eq(
originalSnodePool[0]
);
const lastValidSnodePool = originalSnodePool.map((m, i) => {
if (i !== originalSnodePool.length - 1) {
return {
...m,
storage_server_version: [2, 7, 0],
};
}
return m;
});
expect(OnionPaths.getRandomEdgeSnode(lastValidSnodePool)).to.be.deep.eq(
originalSnodePool[originalSnodePool.length - 1]
);
});
it('random if multiple matches', () => {
const originalSnodePool = generateFakeSnodes(5);
const multipleMatchesSnodePool = originalSnodePool.map((m, i) => {
if (i % 5 === 0) {
return {
...m,
storage_server_version: [2, 7, 0],
};
}
return m;
});
const filtered = originalSnodePool.filter((_m, i) => i % 5 !== 0);
const winner = OnionPaths.getRandomEdgeSnode(multipleMatchesSnodePool);
const winner = OnionPaths.getRandomEdgeSnode(originalSnodePool);
expect(filtered).to.deep.include(winner);
});
it('throws if we run out of snodes with valid version', () => {
const originalSnodePool = generateFakeSnodes(5);
const multipleMatchesSnodePool = originalSnodePool.map(m => {
return {
...m,
storage_server_version: [2, 7, 0],
};
});
expect(() => {
OnionPaths.getRandomEdgeSnode(multipleMatchesSnodePool);
}).to.throw();
});
});
describe('pick edge snode with at least storage server v2.8.0', () => {
@ -211,7 +158,7 @@ describe('OnionPaths', () => {
});
it('throws if we cannot find a valid edge snode', async () => {
const badPool = generateFakeSnodes(20).map(m => {
const badPool = generateFakeSnodes(0).map(m => {
return { ...m, storage_server_version: [2, 1, 1] };
});
fetchSnodePoolFromSeedNodeWithRetries.reset();
@ -229,19 +176,5 @@ describe('OnionPaths', () => {
expect(e.message).to.not.be.eq('fake error');
}
});
it('rebuild a bunch of paths and check that last snode is always >=2.8.0', async () => {
for (let index = 0; index < 1000; index++) {
// build 20 times a path and make sure that the edge snode is always with at least version 2.8.0, when half of the snodes are not upgraded
const pool = generateFakeSnodes(20).map((m, i) => {
return i % 2 === 0 ? { ...m, storage_server_version: [2, 1, 1] } : m;
});
fetchSnodePoolFromSeedNodeWithRetries.resolves(pool);
const newOnionPath = await OnionPaths.getOnionPath({});
expect(newOnionPath.length).to.eq(3);
expect(newOnionPath[2].storage_server_version).to.deep.eq([2, 8, 0]);
}
});
});
});

@ -126,6 +126,15 @@ type ThemeGlobals = {
'--right-panel-attachment-width': string;
'--right-panel-attachment-height': string;
/* Left Panel */
'--left-panel-width': string;
/* Actions panel (the 80px of the 380px of the left pane) */
'--actions-panel-width': string;
/* Main panel */
'--main-panel-content-width': string;
/* Contact Row */
'--contact-row-height': string;
'--contact-row-break-height': string;
@ -239,6 +248,10 @@ export const THEME_GLOBALS: ThemeGlobals = {
'--right-panel-attachment-height':
'calc(var(--right-panel-height) - 2 * var(--margins-2xl) -7px)',
'--left-panel-width': '380px',
'--actions-panel-width': '80px',
'--main-panel-content-width': 'calc(100vw - var(--left-panel-width))',
'--contact-row-height': '60px',
'--contact-row-break-height': '20px',
};

2
ts/window.d.ts vendored

@ -68,7 +68,7 @@ declare global {
persistStore?: Persistor;
restart: () => void;
getSeedNodeList: () => Array<string> | undefined;
setPassword: (newPassword: string | null, oldPassword: string | null) => Promise<void>;
setPassword: (newPassword: string | null, oldPassword: string | null) => Promise<string>;
isOnline: boolean;
toggleMediaPermissions: () => Promise<void>;
toggleCallMediaPermissionsTo: (enabled: boolean) => Promise<void>;

@ -6839,10 +6839,10 @@ semver@^6.0.0, semver@^6.2.0, semver@^6.3.0, semver@^6.3.1:
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4"
integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==
semver@^7.1.2, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.5.4:
version "7.6.2"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.2.tgz#1e3b34759f896e8f14d6134732ce798aeb0c6e13"
integrity sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==
semver@^7.1.2, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.5.0, semver@^7.5.4:
version "7.6.3"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143"
integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==
serialize-error@^7.0.1:
version "7.0.1"
@ -7484,7 +7484,7 @@ tslib@2.6.2:
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae"
integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==
tslib@^2.1.0, tslib@^2.4.0:
tslib@^2.1.0, tslib@^2.4.0, tslib@^2.5.0:
version "2.6.3"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.3.tgz#0438f810ad7a9edcde7a241c3d80db693c8cbfe0"
integrity sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==
@ -8101,6 +8101,16 @@ yargs@^17.0.0, yargs@^17.0.1, yargs@^17.7.2:
y18n "^5.0.5"
yargs-parser "^21.1.1"
yarn-deduplicate@^6.0.2:
version "6.0.2"
resolved "https://registry.yarnpkg.com/yarn-deduplicate/-/yarn-deduplicate-6.0.2.tgz#63498d2d4c3a8567e992a994ce0ab51aa5681f2e"
integrity sha512-Efx4XEj82BgbRJe5gvQbZmEO7pU5DgHgxohYZp98/+GwPqdU90RXtzvHirb7hGlde0sQqk5G3J3Woyjai8hVqA==
dependencies:
"@yarnpkg/lockfile" "^1.1.0"
commander "^10.0.1"
semver "^7.5.0"
tslib "^2.5.0"
yauzl@^2.10.0:
version "2.10.0"
resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9"

Loading…
Cancel
Save