feat: created new recovery phrase ui and qr code with toggling

also allow setting description to render html so we can have line breaks
pull/3083/head
William Grant 1 month ago
parent 2738510cf1
commit a629fa560c

@ -31,6 +31,7 @@ export type SessionIconType =
| 'eye'
| 'eyeDisabled'
| 'exit'
| 'externalLink'
| 'file'
| 'fullscreen'
| 'gear'
@ -47,7 +48,7 @@ export type SessionIconType =
| 'movie'
| 'mute'
| 'oxen'
| 'externalLink'
| 'password'
| 'pause'
| 'pencil'
| 'phone'
@ -218,9 +219,9 @@ export const icons: Record<SessionIconType, IconProps> = {
ratio: 1,
},
copy: {
path: 'M14.2242 15.2325C14.3378 15.124 14.428 14.9946 14.4895 14.8519C14.551 14.7092 14.5826 14.5561 14.5823 14.4014V2.0795C14.5823 1.92477 14.5508 1.77155 14.4898 1.6286C14.4287 1.48565 14.3392 1.35575 14.2264 1.24634C14.1136 1.13693 13.9796 1.05014 13.8322 0.990929C13.6848 0.931716 13.5267 0.901238 13.3672 0.901238H5.27296C4.96712 0.900776 4.67219 1.01148 4.44638 1.2115H3.3418C3.51437 0.855597 3.78729 0.554341 4.12904 0.342562C4.47079 0.130783 4.86739 0.0171364 5.27296 0.0147705H13.3672C13.9319 0.0147705 14.4735 0.232303 14.8728 0.619516C15.2721 1.00673 15.4964 1.5319 15.4964 2.0795V14.4162C15.4954 14.8164 15.3747 15.2078 15.1488 15.5428C14.923 15.8778 14.6018 16.1421 14.2242 16.3037V15.2325ZM2.62547 18.9963C2.06142 18.9953 1.52081 18.7774 1.12232 18.3903C0.723828 18.0031 0.499999 17.4785 0.5 16.9316V4.59116C0.499999 4.0442 0.723828 3.51959 1.12232 3.13248C1.52081 2.74537 2.06142 2.52741 2.62547 2.52643H10.7235C11.2879 2.5274 11.8289 2.74525 12.228 3.13226C12.6271 3.51926 12.8517 4.04386 12.8527 4.59116V16.9316C12.8517 17.4789 12.6271 18.0035 12.228 18.3905C11.8289 18.7775 11.2879 18.9953 10.7235 18.9963H2.62547ZM2.62547 3.4129C2.30387 3.41387 1.99577 3.53845 1.76872 3.75931C1.54167 3.98017 1.41418 4.27931 1.41418 4.59116V16.9316C1.41418 17.2434 1.54167 17.5426 1.76872 17.7634C1.99577 17.9843 2.30387 18.1088 2.62547 18.1098H10.7235C11.0458 18.1098 11.3548 17.9857 11.5827 17.7647C11.8105 17.5438 11.9386 17.2441 11.9386 16.9316V4.59116C11.9386 4.27867 11.8105 3.97898 11.5827 3.75801C11.3548 3.53704 11.0458 3.4129 10.7235 3.4129H2.62547Z',
viewBox: '0 0 16 19',
ratio: 1.19,
path: 'M8.12 6.95h1.47V5.2c0-.7.36-1.09 1.1-1.09h3.15v3.6c0 .94.5 1.42 1.42 1.42h3.32v6.24c0 .7-.36 1.09-1.1 1.09h-1.4v1.47h1.53c1.61 0 2.45-.85 2.45-2.47V9.5c0-.99-.2-1.62-.8-2.23L15.5 3.44a2.74 2.74 0 0 0-2.1-.8h-2.84c-1.6 0-2.44.84-2.44 2.47v1.84Zm6.96.58v-2.8L18.2 7.9h-2.76c-.26 0-.36-.11-.36-.37Z M4.4 19.33c0 1.62.82 2.47 2.44 2.47h7.05c1.61 0 2.44-.85 2.44-2.47v-5.8c0-1.01-.12-1.48-.75-2.13l-4.09-4.14c-.6-.62-1.12-.76-2.03-.76H6.84c-1.61 0-2.45.84-2.45 2.47v10.36Zm1.47-.1V9.06c0-.7.36-1.09 1.1-1.09h2.3v4.13c0 1.08.54 1.6 1.6 1.6h3.99v5.53c0 .7-.37 1.1-1.1 1.1h-6.8c-.73 0-1.1-.4-1.1-1.1Zm5.15-6.83c-.31 0-.44-.13-.44-.44v-3.7l4.07 4.14h-3.63Z',
viewBox: '0 0 25 25',
ratio: 1,
},
crown: {
path: 'M462.3,130.5c-26.7,0-48.5,21.8-48.5,48.5c0,12.9,5,24.5,13.2,33.2c-14.6,16.3-35.7,26.6-59.3,26.6c-1.4,0-2.7,0-4.1-0.1c-36.3-1.8-66.2-28.1-73.7-62.7c8.9-8.8,14.5-21,14.5-34.5c0-0.8,0-1.7-0.1-2.5c-0.2-3.2-0.6-6.4-1.4-9.4 c0-0.1,0-0.2-0.1-0.2c-5.3-20.7-24-36-46.2-36.4c-0.3,0-0.5,0-0.8,0v0c0,0,0,0,0,0c-26.7,0-48.5,21.8-48.5,48.5c0,13.5,5.5,25.7,14.5,34.5c-7.7,35.8-39.6,62.8-77.7,62.8c-23.5,0-44.7-10.3-59.3-26.6c8.2-8.7,13.2-20.4,13.2-33.2c0-26.7-21.8-48.5-48.5-48.5S1.2,152.2,1.2,179c0,23.2,16.3,42.6,38.1,47.4c5.2,42.6,16.1,96.3,39.2,132.9h0V404c0,8.3,6.7,15,15,15H256h162.5c8.3,0,15-6.7,15-15v-44.8h0c5.6-8.8,10.5-18.7,14.7-29.1c13.3-32.8,20.6-71.5,24.5-103.7c21.8-4.8,38.1-24.2,38.1-47.4C510.8,152.2,489.1,130.5,462.3,130.5z',
@ -252,6 +253,11 @@ export const icons: Record<SessionIconType, IconProps> = {
viewBox: '0 0 329.328 329.328',
ratio: 1,
},
externalLink: {
path: 'M20.576 2.125C19.37.921 17.697.687 15.562.687H6.555c-2.104 0-3.779.234-4.985 1.438C.366 3.33.146 4.988.146 7.086v8.942c0 2.139.22 3.788 1.423 4.99 1.208 1.205 2.881 1.437 5.004 1.437h8.99c2.134 0 3.809-.232 5.013-1.438 1.203-1.203 1.424-2.85 1.424-4.99V7.116c0-2.137-.22-3.798-1.424-4.99Zm-.872 4.662v9.56c0 1.226-.155 2.338-.813 2.998-.648.646-1.783.814-2.998.814H6.254c-1.215 0-2.352-.168-3.01-.814-.646-.66-.803-1.772-.803-2.999v-9.53c0-1.237.157-2.368.803-3.016.658-.658 1.805-.817 3.04-.817h9.609c1.215 0 2.35.169 2.998.817.658.658.813 1.77.813 2.987ZM14.735 14.61c.584 0 .96-.442.96-1.061V8.094c0-.802-.45-1.162-1.176-1.162H9.033c-.635 0-1.04.376-1.04.959s.412.959 1.053.959h1.979l1.607-.188-1.741 1.592-4.106 4.115c-.198.198-.33.475-.33.75 0 .617.424 1.02 1.018 1.02.317 0 .578-.116.788-.324l4.095-4.093 1.582-1.723-.171 1.694v1.87c0 .634.376 1.048.968 1.048Z',
viewBox: '0 0 22 23',
ratio: 1,
},
eye: {
path: 'M37.5,55.3c15.9,0,26.7-12.9,26.7-16.8s-10.8-16.8-26.7-16.8-26.7,12.8-26.7,16.8,11,16.8,26.7,16.8Z M37.5,51.6c-12.4,0-22.3-10.4-22.3-13.1s9.9-13.1,22.3-13.1,22.3,10.8,22.3,13.1-9.9,13.1-22.3,13.1Z M37.5,27.5c-6.1,0-11,4.8-11,11,0,6,4.9,11,11,11s11-5,11-11-4.9-11-11-11ZM37.5,42c-2,0-3.6-1.6-3.6-3.6s1.6-3.5,3.6-3.5,3.6,1.6,3.6,3.5-1.6,3.6-3.6,3.6Z',
viewBox: '0 0 75 76',
@ -342,9 +348,9 @@ export const icons: Record<SessionIconType, IconProps> = {
viewBox: '0 0 1000 214.3',
ratio: 4,
},
externalLink: {
path: 'M20.576 2.125C19.37.921 17.697.687 15.562.687H6.555c-2.104 0-3.779.234-4.985 1.438C.366 3.33.146 4.988.146 7.086v8.942c0 2.139.22 3.788 1.423 4.99 1.208 1.205 2.881 1.437 5.004 1.437h8.99c2.134 0 3.809-.232 5.013-1.438 1.203-1.203 1.424-2.85 1.424-4.99V7.116c0-2.137-.22-3.798-1.424-4.99Zm-.872 4.662v9.56c0 1.226-.155 2.338-.813 2.998-.648.646-1.783.814-2.998.814H6.254c-1.215 0-2.352-.168-3.01-.814-.646-.66-.803-1.772-.803-2.999v-9.53c0-1.237.157-2.368.803-3.016.658-.658 1.805-.817 3.04-.817h9.609c1.215 0 2.35.169 2.998.817.658.658.813 1.77.813 2.987ZM14.735 14.61c.584 0 .96-.442.96-1.061V8.094c0-.802-.45-1.162-1.176-1.162H9.033c-.635 0-1.04.376-1.04.959s.412.959 1.053.959h1.979l1.607-.188-1.741 1.592-4.106 4.115c-.198.198-.33.475-.33.75 0 .617.424 1.02 1.018 1.02.317 0 .578-.116.788-.324l4.095-4.093 1.582-1.723-.171 1.694v1.87c0 .634.376 1.048.968 1.048Z',
viewBox: '0 0 22 23',
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',
viewBox: '0 0 43 43',
ratio: 1,
},
pause: {
@ -450,8 +456,8 @@ export const icons: Record<SessionIconType, IconProps> = {
ratio: 1,
},
qr: {
path: 'M0 0v170h170V0H0zm130 130H40V40h90v90z M65 65h40v40H65zM342 0v170h170V0H342zm130 130h-90V40h90v90z M407 65h40v40h-40zM0 342v170h170V342H0zm130 130H40v-90h90v90z M65 407h40v40H65zM40 197h40v40H40zM120 277v-40H80v40h39v40h40v-40zM280 77h40v40h-40zM200 40h40v77h-40zM240 0h40v40h-40zM240 117v40h-40v40h80v-80zM280 355v-39h-40v-79h-40v80h40v39h40v39h80v-40z M280 197h40v80h-40zM472 236v-39h-73v40h-39v40h40v39h112v-80h-40zm0 40h-72v-39h72v39zM472 355h40v80h-40zM320 277h40v40h-40zM360 395h40v40h-40zM400 355h40v40h-40zM400 435v77h40v-37h32v-40zM200 356h40v76h-40zM320 472v-40h-80v80h40v-40h39v40h40v-40zM120 197h80v40h-80zM0 237h40v80H0z',
viewBox: '0 0 512 512',
path: 'M9.64 3.4h-6.8v6.4h6.8V3.4ZM8.42 8.66H4.06V4.55h4.36v4.11ZM2.85 20.42h6.79V14h-6.8v6.4Zm1.21-5.26h4.36v4.11H4.06v-4.11ZM20.68 3.4h-6.8v6.4h6.8V3.4Zm-1.22 5.26H15.1V4.55h4.36v4.11Z M18.58 5.38h-2.6v2.45h2.6V5.38Zm-1.22 1.3h-.16v-.15h.16v.15ZM7.54 5.38h-2.6v2.45h2.6V5.38Zm-1.22 1.3h-.16v-.15h.16v.15ZM4.95 18.45h2.59v-2.44h-2.6v2.44Zm1.21-1.3h.16v.15h-.16v-.15Z M19.82 17.21h-1.18v-1.13H16.2V17h-.9v-.92h-1.06v-.94h3.24v-2.26H15.3v-2.13H12V9.8h1.08V7.46h-1.09v-.68h1.09V4.43h-1.09V3.4h-1.38v4.4h1.08v1.88h-1.08v.97H9.4v1.16h-.77v-1.16H6.12v1.14h-.76v-1.14H2.85v2.45h3.39v-1.04h2.02v1.06h2.29v2.2h2.2v.76h-2.2v1.2h1.18v.88h-1.18v2.26h1.4v-2.06h.89v2.06h2.46v-2.1h.82v2.1h1.4v-2.26h-1.04v-.89h1.93v3.15h2.38v-2.13h-.97v-1.07Zm-5.95-3.38v1.1h-.73v-1.92h1.95v.82h-1.22Zm-3.09-2.85h.91v1.08h1.22v.82h-2.13v-1.9Zm1.15 3.2h-.17v-.15h.17v.15Zm1.21 2.16h.76v1.06h1.19v.75h-1.95v-1.81Z M20.79 13.88h-2.6v1.33h1.19v1.13h1.4v-2.46ZM20.68 13v-2.25H16v1.3h2.27v.96h2.4Z',
viewBox: '0 0 24 24',
ratio: 1,
},
question: {

@ -26,7 +26,6 @@ export const StyledDescriptionSettingsItem = styled.div`
font-family: var(--font-default);
font-size: var(--font-size-sm);
font-weight: 400;
max-width: 700px;
`;
export const StyledTitleSettingsItem = styled.div`
@ -73,8 +72,8 @@ const StyledSettingItemClickable = styled(StyledSettingItemInline)`
`;
export const SettingsTitleAndDescription = (props: {
title?: string;
description?: string;
title?: string | ReactNode;
description?: string | ReactNode;
childrenDescription?: ReactNode;
}) => {
const { description, childrenDescription, title } = props;
@ -93,8 +92,8 @@ export const SettingsTitleAndDescription = (props: {
export const SessionSettingsItemWrapper = (props: {
inline: boolean;
title?: string;
description?: string;
title?: string | ReactNode;
description?: string | ReactNode;
children?: ReactNode;
childrenDescription?: ReactNode;
}) => {

@ -2,6 +2,7 @@ import { isEmpty } from 'lodash';
import { useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import useMount from 'react-use/lib/useMount';
import styled from 'styled-components';
import { usePasswordModal } from '../../../hooks/usePasswordModal';
import { mnDecode } from '../../../session/crypto/mnemonic';
import { ToastUtils } from '../../../session/utils';
@ -10,12 +11,38 @@ import { getTheme } from '../../../state/selectors/theme';
import { getThemeValue } from '../../../themes/globals';
import { getCurrentRecoveryPhrase } from '../../../util/storage';
import { SessionQRCode } from '../../SessionQRCode';
import { AnimatedFlex } from '../../basic/Flex';
import { SessionHtmlRenderer } from '../../basic/SessionHTMLRenderer';
import { SpacerMD, SpacerSM } from '../../basic/Text';
import { SessionIconButton } from '../../icon';
import { SessionSettingsItemWrapper } from '../SessionSettingListItem';
const StyledSettingsItemContainer = styled.div`
p {
font-size: var(--font-size-md);
line-height: 30px;
margin: 0;
}
`;
const StyledRecoveryPassword = styled(AnimatedFlex)`
font-family: var(--font-mono);
font-size: var(--font-size-sm);
text-align: justify;
user-select: text;
border: 2px solid var(--text-secondary-color);
border-radius: 11px;
padding: var(--margins-sm) var(--margins-sm) var(--margins-sm) var(--margins-md);
margin: 0;
color: var(--primary-color);
max-width: fit-content;
`;
export const SettingsCategoryRecoveryPassword = () => {
const [loadingSeed, setLoadingSeed] = useState(true);
const [recoveryPhrase, setRecoveryPhrase] = useState('');
const [hexEncodedSeed, setHexEncodedSeed] = useState('');
const [isQRVisible, setIsQRVisible] = useState(false);
const dispatch = useDispatch();
@ -52,25 +79,43 @@ export const SettingsCategoryRecoveryPassword = () => {
}
return (
<>
<StyledSettingsItemContainer>
<SessionSettingsItemWrapper
// TODO need to support escaping the HTML or passing through a ReactNode
title={window.i18n('sessionRecoveryPassword')}
description={window.i18n('recoveryPasswordDescription')}
description={
<SessionHtmlRenderer tag="p" html={window.i18n('recoveryPasswordDescription')} />
}
inline={false}
>
<i
onClick={() => {
if (isEmpty(recoveryPhrase)) {
return;
}
copyRecoveryPhrase(recoveryPhrase);
}}
className="session-modal__text-highlight"
<SpacerMD />
<StyledRecoveryPassword
container={true}
flexDirection={'row'}
justifyContent={'space-between'}
alignItems={'center'}
width={'100%'}
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
// initial load has some flickering, so we add a small delay
transition={{ duration: 0.05 }}
style={{ display: isQRVisible ? 'none' : 'flex' }}
data-testid="recovery-phrase-seed-modal"
>
{recoveryPhrase}
</i>
<SpacerSM />
<SessionIconButton
aria-label={'copy to clipboard button'}
iconType={'copy'}
iconSize={'huge'}
iconColor={'var(--text-primary-color)'}
onClick={() => {
if (isEmpty(recoveryPhrase)) {
return;
}
copyRecoveryPhrase(recoveryPhrase);
}}
/>
</StyledRecoveryPassword>
<SessionQRCode
id={'session-recovery-passwod'}
value={hexEncodedSeed}
@ -85,10 +130,29 @@ export const SettingsCategoryRecoveryPassword = () => {
logoWidth={56}
logoHeight={56}
logoIsSVG={true}
style={{ display: isQRVisible ? 'flex' : 'none' }}
/>
{/* TODO Toggling between QR and recovery password */}
<SpacerMD />
<SessionIconButton
aria-label={isQRVisible ? 'show password button' : 'show qr code button'}
iconType={isQRVisible ? 'password' : 'qr'}
iconSize={isQRVisible ? 48 : 'huge'}
iconColor={'var(--text-primary-color)'}
onClick={() => setIsQRVisible(!isQRVisible)}
padding="0"
style={{
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
gap: isQRVisible ? undefined : 'var(--margins-xs)',
marginLeft: isQRVisible ? '-8px' : undefined,
}}
>
{isQRVisible ? 'View as Password' : 'View QR'}
</SessionIconButton>
{/* TODO Permenantly hide button */}
</SessionSettingsItemWrapper>
</>
</StyledSettingsItemContainer>
);
};

Loading…
Cancel
Save