feat: new sessionqrcode component

updated account id and recovery password qr codes with logos
pull/3083/head
William Grant 12 months ago
parent ab093ffc62
commit 0d3c058137

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

@ -8,6 +8,7 @@ import { persistStore } from 'redux-persist';
import { PersistGate } from 'redux-persist/integration/react';
import styled from 'styled-components';
import { AnimatePresence } from 'framer-motion';
import { LeftPane } from './leftpane/LeftPane';
// moment does not support es-419 correctly (and cause white screen on app start)
import { getConversationController } from '../session/conversations';
@ -132,12 +133,14 @@ export const SessionInboxView = () => {
<Provider store={window.inboxStore}>
<PersistGate loading={null} persistor={persistor}>
<SomeDeviceOutdatedSyncingNotice />
<Flex container={true} height="0" flexShrink={100} flexGrow={1}>
<StyledGutter>
<LeftPane />
</StyledGutter>
<SessionMainPanel />
</Flex>
<AnimatePresence>
<Flex container={true} height="0" flexShrink={100} flexGrow={1}>
<StyledGutter>
<LeftPane />
</StyledGutter>
<SessionMainPanel />
</Flex>
</AnimatePresence>
</PersistGate>
</Provider>
</div>

@ -0,0 +1,69 @@
import { isEmpty } from 'lodash';
import { MouseEvent } from 'react';
import { QRCode } from 'react-qrcode-logo';
import styled, { CSSProperties } from 'styled-components';
import { THEME_GLOBALS } from '../themes/globals';
import { saveQRCode } from '../util/saveQRCode';
import { AnimatedFlex } from './basic/Flex';
// We fade in the QR code to hide the logo flickering on first render
const StyledQRView = styled(AnimatedFlex)`
cursor: pointer;
border-radius: var(--border-radius);
overflow: hidden;
`;
type Props = {
id: string;
value: string;
size: number;
backgroundColor?: string;
foregroundColor?: string;
logoImage?: string;
logoWidth?: number;
logoHeight?: number;
style?: CSSProperties;
};
export function SessionQRCode(props: Props) {
const {
id,
value,
size,
backgroundColor = '#FFF',
foregroundColor = '#000',
logoImage,
logoWidth,
logoHeight,
style,
} = props;
return (
<StyledQRView
container={true}
aria-label={window.i18n('clickToTrustContact')}
title={window.i18n('clickToTrustContact')}
onClick={(event: MouseEvent) => {
event.preventDefault();
saveQRCode(id);
}}
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ duration: THEME_GLOBALS['--default-duration-seconds'] }}
style={style}
>
<QRCode
id={id}
value={value}
ecLevel={'Q'}
size={size}
quietZone={10}
bgColor={backgroundColor}
fgColor={foregroundColor}
logoImage={logoImage}
logoWidth={logoWidth}
logoHeight={logoHeight}
removeQrCodeBehindLogo={!isEmpty(logoImage)}
/>
</StyledQRView>
);
}

@ -1,3 +1,4 @@
import { motion } from 'framer-motion';
import styled from 'styled-components';
import { HTMLDirection } from '../../util/i18n';
@ -58,3 +59,21 @@ export const Flex = styled.div<FlexProps>`
min-width: ${props => props.minWidth || 'none'};
direction: ${props => props.dir || undefined};
`;
export const AnimatedFlex = styled(motion.div)<FlexProps>`
display: ${props => (props.container ? 'flex' : 'block')};
justify-content: ${props => props.justifyContent || 'flex-start'};
flex-direction: ${props => props.flexDirection || 'row'};
flex-grow: ${props => (props.flexGrow !== undefined ? props.flexGrow : '0')};
flex-basis: ${props => (props.flexBasis !== undefined ? props.flexBasis : 'auto')};
flex-shrink: ${props => (props.flexShrink !== undefined ? props.flexShrink : '1')};
flex-wrap: ${props => (props.flexWrap !== undefined ? props.flexWrap : 'nowrap')};
align-items: ${props => props.alignItems || 'stretch'};
margin: ${props => props.margin || '0'};
padding: ${props => props.padding || '0'};
width: ${props => props.width || 'auto'};
height: ${props => props.height || 'auto'};
max-width: ${props => props.maxWidth || 'none'};
min-width: ${props => props.minWidth || 'none'};
direction: ${props => props.dir || undefined};
`;

@ -1,7 +1,5 @@
import { ChangeEvent, MouseEvent, useState } from 'react';
import { QRCode } from 'react-qrcode-logo';
import { useDispatch } from 'react-redux';
import styled from 'styled-components';
import { ChangeEvent, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { Avatar, AvatarSize } from '../avatar/Avatar';
import { SyncUtils, ToastUtils, UserUtils } from '../../session/utils';
@ -13,35 +11,33 @@ import { MAX_NAME_LENGTH_BYTES } from '../../session/constants';
import { getConversationController } from '../../session/conversations';
import { sanitizeSessionUsername } from '../../session/utils/String';
import { editProfileModal, updateEditProfilePictureModel } from '../../state/ducks/modalDialog';
import { saveQRCode } from '../../util/saveQRCode';
import { getTheme } from '../../state/selectors/theme';
import { getThemeValue } from '../../themes/globals';
import { setLastProfileUpdateTimestamp } from '../../util/storage';
import { SessionQRCode } from '../SessionQRCode';
import { SessionWrapperModal } from '../SessionWrapperModal';
import { Flex } from '../basic/Flex';
import { SessionButton, SessionButtonType } from '../basic/SessionButton';
import { SessionIconButton } from '../icon';
import { SessionSpinner } from '../loading';
const qrCodeId = 'session-account-id';
const handleSaveQRCode = (event: MouseEvent) => {
event.preventDefault();
saveQRCode(qrCodeId);
};
const StyledQRView = styled(Flex)`
cursor: pointer;
`;
const QRView = ({ sessionID }: { sessionID: string }) => {
const theme = useSelector(getTheme);
return (
<StyledQRView
container={true}
aria-label={window.i18n('clickToTrustContact')}
title={window.i18n('clickToTrustContact')}
className="qr-image"
onClick={handleSaveQRCode}
>
<QRCode id={qrCodeId} value={sessionID} ecLevel={'Q'} size={220} quietZone={10} />
</StyledQRView>
<SessionQRCode
id={'session-account-id'}
value={sessionID}
size={170}
backgroundColor={getThemeValue(
theme.includes('dark') ? '--text-primary-color' : '--background-primary-color'
)}
foregroundColor={getThemeValue(
theme.includes('dark') ? '--background-primary-color' : '--text-primary-color'
)}
logoImage={`./images/session/brand/${theme}.png`}
logoWidth={42}
logoHeight={44}
/>
);
};

@ -1,9 +1,8 @@
import { MouseEvent, useState } from 'react';
import { useDispatch } from 'react-redux';
import { useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import useMount from 'react-use/lib/useMount';
import styled from 'styled-components';
import { QRCode } from 'react-qrcode-logo';
import { Data } from '../../data/data';
import { ToastUtils } from '../../session/utils';
import { matchesHash } from '../../util/passwordUtils';
@ -12,10 +11,11 @@ import { mnDecode } from '../../session/crypto/mnemonic';
import { recoveryPhraseModal } from '../../state/ducks/modalDialog';
import { SpacerSM } from '../basic/Text';
import { saveQRCode } from '../../util/saveQRCode';
import { getTheme } from '../../state/selectors/theme';
import { getThemeValue } from '../../themes/globals';
import { getCurrentRecoveryPhrase } from '../../util/storage';
import { SessionQRCode } from '../SessionQRCode';
import { SessionWrapperModal } from '../SessionWrapperModal';
import { Flex } from '../basic/Flex';
import { SessionButton, SessionButtonColor, SessionButtonType } from '../basic/SessionButton';
interface PasswordProps {
@ -100,21 +100,11 @@ interface SeedProps {
const StyledRecoveryPhrase = styled.i``;
const StyledQRImage = styled(Flex)`
margin: 0 auto var(--margins-lg);
cursor: pointer;
`;
const qrCodeId = 'session-recovery-password';
const handleSaveQRCode = (event: MouseEvent) => {
event.preventDefault();
saveQRCode(qrCodeId);
};
const Seed = (props: SeedProps) => {
const { recoveryPhrase, onClickCopy } = props;
const i18n = window.i18n;
const dispatch = useDispatch();
const theme = useSelector(getTheme);
const hexEncodedSeed = mnDecode(recoveryPhrase, 'english');
@ -142,15 +132,21 @@ const Seed = (props: SeedProps) => {
{i18n('recoveryPhraseSavePromptMain')}
</p>
<StyledQRImage
container={true}
aria-label={window.i18n('clickToTrustContact')}
title={window.i18n('clickToTrustContact')}
className="qr-image"
onClick={handleSaveQRCode}
>
<QRCode id={qrCodeId} value={hexEncodedSeed} ecLevel={'Q'} size={220} quietZone={10} />
</StyledQRImage>
<SessionQRCode
id={'session-recovery-passwod'}
value={hexEncodedSeed}
size={240}
backgroundColor={getThemeValue(
theme.includes('dark') ? '--text-primary-color' : '--background-primary-color'
)}
foregroundColor={getThemeValue(
theme.includes('dark') ? '--background-primary-color' : '--text-primary-color'
)}
logoImage={`./images/session/shield/${theme}.png`}
logoWidth={60}
logoHeight={60}
style={{ margin: '0 auto var(--margins-lg)' }}
/>
<StyledRecoveryPhrase
data-testid="recovery-phrase-seed-modal"

@ -1,6 +1,7 @@
import { isTestIntegration } from '../shared/env_vars';
import { hexColorToRGB } from '../util/hexColorToRGB';
import { COLORS } from './constants/colors';
import { ThemeColorVariables } from './variableColors';
function setDuration(duration: number | string) {
return `${!isTestIntegration() ? duration : typeof duration === 'string' ? '0s' : '0'}`;
@ -188,3 +189,8 @@ export function declareCSSVariables(variables: Record<string, string>) {
return output;
}
type ThemeKeys = ThemeGlobals & ThemeColorVariables;
export function getThemeValue(key: keyof ThemeKeys) {
return getComputedStyle(document.documentElement).getPropertyValue(key);
}

Loading…
Cancel
Save