wip: adding recovery phrase prompt.

pull/1846/head
Warrick Corfe-Tan 4 years ago
parent bfed4a88dd
commit b0a8c6c3eb

@ -426,5 +426,12 @@
"dialogClearAllDataDeletionFailedMultiple": "Data not deleted by those Service Nodes: $snodes$", "dialogClearAllDataDeletionFailedMultiple": "Data not deleted by those Service Nodes: $snodes$",
"dialogClearAllDataDeletionQuestion": "Would you like to clear only this device, or delete your entire account?", "dialogClearAllDataDeletionQuestion": "Would you like to clear only this device, or delete your entire account?",
"deviceOnly": "Device Only", "deviceOnly": "Device Only",
"entireAccount": "Entire Account" "entireAccount": "Entire Account",
"recoveryPhraseSecureMessage": "Secure your account by saving your recovery phrase",
"recoveryPhraseSecureTitle": "You're almost finished!",
"recoveryPhraseSecureButtonText": "Secure your account",
"recoveryPhraseRevealMessage": "Reveal your recovery phrase then store it safely to secure it",
"recoveryPhraseRevealButtonText": "Reveal Recovery Phrase",
"recoveryPhraseInfoMessage": "Meet your recovery phrase Your recovery phrase is the master key to your session ID - you can use it to restore your Session ID if you lose access to your device, Store your recovery phrase in a safe place, and don't give it to anyone.",
"recoveryPhraseCompleteTitle": "Account secured!"
} }

@ -11,6 +11,7 @@ import { SessionWrapperModal } from '../session/SessionWrapperModal';
const deleteDbLocally = async () => { const deleteDbLocally = async () => {
window?.log?.info('configuration message sent successfully. Deleting everything'); window?.log?.info('configuration message sent successfully. Deleting everything');
window.persistStore?.purge();
await window.Signal.Logs.deleteAll(); await window.Signal.Logs.deleteAll();
await window.Signal.Data.removeAll(); await window.Signal.Data.removeAll();
await window.Signal.Data.close(); await window.Signal.Data.close();

@ -1,8 +1,13 @@
import React from 'react'; import React, { useState } from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
import { SessionIcon, SessionIconSize, SessionIconType } from './icon'; import { SessionIcon, SessionIconSize, SessionIconType } from './icon';
import { DefaultTheme, useTheme } from 'styled-components'; import styled, { DefaultTheme, useTheme } from 'styled-components';
import { SessionButton } from './SessionButton'; import { SessionButton, SessionButtonColor, SessionButtonType } from './SessionButton';
import { Constants } from '../../session';
import { UserUtils } from '../../session/utils';
import { useDispatch, useSelector } from 'react-redux';
import { disableRecoveryPhrasePrompt } from '../../state/ducks/userConfig';
import { getShowRecoveryPhrasePrompt } from '../../state/selectors/userConfig';
const Tab = ({ const Tab = ({
isSelected, isSelected,
@ -17,8 +22,8 @@ const Tab = ({
}) => { }) => {
const handleClick = onSelect const handleClick = onSelect
? () => { ? () => {
onSelect(type); onSelect(type);
} }
: undefined; : undefined;
return ( return (
@ -40,22 +45,232 @@ type Props = {
export const LeftPaneSectionHeader = (props: Props) => { export const LeftPaneSectionHeader = (props: Props) => {
const { label, buttonIcon, buttonClicked } = props; const { label, buttonIcon, buttonClicked } = props;
const theme = useTheme(); const theme = useTheme();
const showRecoveryPhrasePrompt = useSelector(getShowRecoveryPhrasePrompt);
return ( return (
<div className="module-left-pane__header"> <StyledLeftPaneHeaderContainer>
{label && <Tab label={label} type={0} isSelected={true} key={label} />} <div className="module-left-pane__header">
{buttonIcon && ( {label && <Tab label={label} type={0} isSelected={true} key={label} />}
<SessionButton onClick={buttonClicked} key="compose" theme={theme}> {buttonIcon && (
<SessionIcon <SessionButton onClick={buttonClicked} key="compose" theme={theme}>
iconType={buttonIcon} <SessionIcon
iconSize={SessionIconSize.Small} iconType={buttonIcon}
iconColor="white" iconSize={SessionIconSize.Small}
theme={theme} iconColor="white"
/> theme={theme}
</SessionButton> />
)} </SessionButton>
</div> )}
</div>
{showRecoveryPhrasePrompt && <LeftPaneBanner />}
</StyledLeftPaneHeaderContainer>
); );
}; };
export const LeftPaneBanner = (Props: any) => {
const [completion, setCompletion] = useState(80);
const [bodyText, setBodyText] = useState(window.i18n('recoveryPhraseSecureMessage'));
const [buttonText, setButtonText] = useState(window.i18n('recoveryPhraseSecureButtonText'));
const [recoveryPhraseHidden, setRecoveryPhraseHidden] = useState(true);
const [isCompleted, setIsCompleted] = useState(false);
const [bannerTitle, setBannerTitle] = useState(window.i18n("recoveryPhraseSecureTitle"));
const recoveryPhrase = UserUtils.getCurrentRecoveryPhrase();
const secondsBeforeRemoval = 2 * 1000;
const completionText = `${completion}%`;
const handleShowRecoveryClick = () => {
setRecoveryPhraseHidden(false);
setBodyText(window.i18n('recoveryPhraseInfoMessage'));
setButtonText(window.i18n('copy'));
}
const handleSecureClick = () => {
if (completion === 80) {
setCompletion(90);
setBodyText(window.i18n('recoveryPhraseRevealMessage'));
setButtonText(window.i18n('recoveryPhraseRevealButtonText'));
}
}
const BannerInner = (props: any) => {
const dispatch = useDispatch();
const handleCopyPhraseClick = async () => {
await navigator.clipboard.writeText(recoveryPhrase);
setCompletion(100)
setBannerTitle(window.i18n('recoveryPhraseCompleteTitle'));
setBodyText('');
setRecoveryPhraseHidden(true);
setIsCompleted(true);
// remove banner after a small delay
setTimeout(() => {
dispatch(disableRecoveryPhrasePrompt());
}, secondsBeforeRemoval);
}
let onClick =
completion === 80 ? handleSecureClick :
completion === 90 ?
recoveryPhraseHidden ?
handleShowRecoveryClick :
handleCopyPhraseClick
: null;
// TODO: This can be refactored down. all returns have p tag + button, final has conditional phrase element.
return (
<StyledBannerInner>
<p>
{bodyText}
</p>
{!recoveryPhraseHidden &&
<StyledRecoveryPhrase
theme={theme}
className="left-pane-banner___phrase" onClick={handleShowRecoveryClick}>
{recoveryPhrase}
</StyledRecoveryPhrase>
}
{!isCompleted &&
<SessionButton
buttonType={SessionButtonType.Default}
text={buttonText}
onClick={onClick}
/>
}
</StyledBannerInner>
)
}
const useColumn = completion === 90 && handleShowRecoveryClick;
const theme = useTheme();
return (
<StyledLeftPaneBanner
border={useTheme().colors.sessionBorder}
isCompleted={isCompleted}>
<StyledProgressBarContainer>
<StyledProgressBarInner
color={Constants.UI.COLORS.GREEN}
width={completion + '%'}
/>
</StyledProgressBarContainer>
<StyledBannerTitle
theme={theme}>
{bannerTitle} <span>{completionText}</span>
</StyledBannerTitle>
<StyledBannerContainer flexDirection={useColumn ? 'column' : 'row'} >
<BannerInner />
</StyledBannerContainer>
</StyledLeftPaneBanner>
)
}
interface StyledProgressBarContainerProps {
theme: DefaultTheme;
}
const StyledProgressBarContainer = styled.div`
width: 100%;
height: 5px;
flex-direction: row;
background: ${(p: StyledProgressBarContainerProps) => p.theme.colors.sessionBorderColor};
`;
interface StyledProgressBarProps {
width: string;
color?: string;
}
const StyledProgressBarInner = styled.div`
background: ${(p: StyledProgressBarProps) => p.color};
width: ${(p: StyledProgressBarProps) => p.width};
transition: width 0.5s ease-in;
height: 100%;
`;
interface StyledBannerTitle {
theme: DefaultTheme;
}
export const StyledBannerTitle = styled.div`
line-height: 1.3;
font-size: ${(p: StyledBannerTitle) => p.theme.common.fonts.md};
font-weight: bold;
margin:
${Constants.UI.SPACING.marginSm}
${Constants.UI.SPACING.marginSm}
0
${Constants.UI.SPACING.marginSm};
span {
color: ${(p: StyledBannerTitle) => p.theme.colors.textAccent};
}
`;
interface StyledLeftPaneBannerProps {
isCompleted?: boolean;
border: string;
theme: DefaultTheme;
}
export const StyledLeftPaneBanner = styled.div`
background: ${(p: StyledLeftPaneBannerProps) => p.theme.colors.recoveryPhraseBannerBackground};
display: flex;
flex-direction: column;
border-bottom: ${(p: StyledLeftPaneBannerProps) => p.border};
opacity: 1;
transition: opacity 2s;
${(p: StyledLeftPaneBannerProps) => p.isCompleted === true ?
`
opacity: 0;
`
:
null
}
`;
const StyledBannerInner = styled.div`
p {
margin: 0;
}
.left-pane-banner___phrase {
margin-top: ${Constants.UI.SPACING.marginMd};
}
.session-button {
margin-top: ${Constants.UI.SPACING.marginSm};
}
`;
interface StyledRecoveryPhraseProps {
theme: DefaultTheme;
}
const StyledRecoveryPhrase = styled.p`
margin: ${Constants.UI.SPACING.marginXs};
border-radius: 5px;
padding: 5px;
border: ${(props: StyledRecoveryPhraseProps) => props.theme.colors.sessionBorderHighContrast};
`;
// 90%
// tap and hold the redacted words to reveal your recovery phrase then store it safely to secure
// meet your recovery phrase
// your recovery phrase is the master key to your session ID - you can use it to restore your Session ID if you lose access to your device, Store your recovery phrase in a safe place, and don't give it to anyone.
interface StyledBannerContainerProps {
flexDirection?: string;
}
export const StyledBannerContainer = styled.div`
display: flex;
flex-direction: ${(p: StyledBannerContainerProps) => p.flexDirection};
justify-content: space-between;
padding: ${Constants.UI.SPACING.marginSm}
`;
export const StyledLeftPaneHeaderContainer = styled.div`
display: flex;
flex-direction: column;
`;

@ -1,4 +1,4 @@
import React, { useState } from 'react'; import React from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
import { SessionButton, SessionButtonColor, SessionButtonType } from './SessionButton'; import { SessionButton, SessionButtonColor, SessionButtonType } from './SessionButton';
@ -13,6 +13,12 @@ import { getFocusedSettingsSection } from '../../state/selectors/section';
import { getTheme } from '../../state/selectors/theme'; import { getTheme } from '../../state/selectors/theme';
import { recoveryPhraseModal, updateDeleteAccountModal } from '../../state/ducks/modalDialog'; import { recoveryPhraseModal, updateDeleteAccountModal } from '../../state/ducks/modalDialog';
type Props = {
settingsCategory: SessionSettingCategory;
showSettingsSection: (category: SessionSettingCategory) => void;
theme: DefaultTheme;
};
const getCategories = () => { const getCategories = () => {
return [ return [
{ {

@ -52,6 +52,7 @@ export class SessionInboxView extends React.Component<any, State> {
} }
const persistor = persistStore(this.store); const persistor = persistStore(this.store);
window.persistStore = persistor;
return ( return (
<Provider store={this.store}> <Provider store={this.store}>

@ -3,12 +3,11 @@ import classNames from 'classnames';
import moment from 'moment'; import moment from 'moment';
import { SessionIconButton, SessionIconSize, SessionIconType } from '../icon'; import { SessionIconButton, SessionIconSize, SessionIconType } from '../icon';
import { SessionButton, SessionButtonColor, SessionButtonType } from '../SessionButton';
import { Constants } from '../../../session'; import { Constants } from '../../../session';
import { ToastUtils } from '../../../session/utils'; import { ToastUtils } from '../../../session/utils';
import autoBind from 'auto-bind'; import autoBind from 'auto-bind';
import MicRecorder from 'mic-recorder-to-mp3'; import MicRecorder from 'mic-recorder-to-mp3';
import styled, { useTheme } from 'styled-components'; import styled from 'styled-components';
interface Props { interface Props {
onExitVoiceNoteView: any; onExitVoiceNoteView: any;
@ -164,7 +163,7 @@ class SessionRecordingInner extends React.Component<Props, State> {
)} )}
{hasRecording && ( {hasRecording && (
<SessionIconButton <SessionIconButton
iconType={SessionIconType.Delete2} iconType={SessionIconType.Delete}
iconSize={SessionIconSize.Medium} iconSize={SessionIconSize.Medium}
onClick={this.onDeleteVoiceMessage} onClick={this.onDeleteVoiceMessage}
/> />
@ -366,7 +365,6 @@ class SessionRecordingInner extends React.Component<Props, State> {
const audioURL = window.URL.createObjectURL(this.audioBlobMp3); const audioURL = window.URL.createObjectURL(this.audioBlobMp3);
this.audioElement = new Audio(audioURL); this.audioElement = new Audio(audioURL);
// ww adding record duration
this.setState({ this.setState({
recordDuration: this.audioElement.duration, recordDuration: this.audioElement.duration,
}); });

@ -13,8 +13,6 @@ export enum SessionIconType {
CircleElipses = 'circleElipses', CircleElipses = 'circleElipses',
Contacts = 'contacts', Contacts = 'contacts',
Delete = 'delete', Delete = 'delete',
Delete2 = 'delete2',
Delete3 = 'delete3',
Ellipses = 'ellipses', Ellipses = 'ellipses',
Emoji = 'emoji', Emoji = 'emoji',
Error = 'error', Error = 'error',
@ -130,23 +128,11 @@ export const icons = {
ratio: 1, ratio: 1,
}, },
[SessionIconType.Delete]: { [SessionIconType.Delete]: {
path:
'M1.63 97.99l36.55-36.55L1.63 24.89c-2.17-2.17-2.17-5.73 0-7.9L16.99 1.63c2.17-2.17 5.73-2.17 7.9 0l36.55 36.55L97.99 1.63c2.17-2.17 5.73-2.17 7.9 0l15.36 15.36c2.17 2.17 2.17 5.73 0 7.9L84.7 61.44l36.55 36.55c2.17 2.17 2.17 5.73 0 7.9l-15.36 15.36c-2.17 2.17-5.73 2.17-7.9 0L61.44 84.7l-36.55 36.55c-2.17 2.17-5.73 2.17-7.9 0L1.63 105.89c-2.17-2.17-2.17-5.73 0-7.9z',
viewBox: '0 0 122.88 122.88',
ratio: 1,
},
[SessionIconType.Delete2]: {
path: path:
'M11.17 37.16h83.48a8.4 8.4 0 012 .16 5.93 5.93 0 012.88 1.56 5.43 5.43 0 011.64 3.34 7.65 7.65 0 01-.06 1.44L94 117.31V117.72a7.06 7.06 0 01-.2.9v.06a5.89 5.89 0 01-5.47 4.07H17.32a6.17 6.17 0 01-1.25-.19 6.17 6.17 0 01-1.16-.48 6.18 6.18 0 01-3.08-4.88l-7-73.49a7.69 7.69 0 01-.06-1.66 5.37 5.37 0 011.63-3.29 6 6 0 013-1.58 8.94 8.94 0 011.79-.13zM5.65 8.8h31.47V6a2.44 2.44 0 010-.27 6 6 0 011.76-4A6 6 0 0143.09 0h19.67a6 6 0 015.7 6v2.8h32.39a4.7 4.7 0 014.31 4.43v10.36a2.59 2.59 0 01-2.59 2.59H2.59A2.59 2.59 0 010 23.62V13.53a1.56 1.56 0 010-.31 4.72 4.72 0 013.88-4.34 10.4 10.4 0 011.77-.08zm42.1 52.7a4.77 4.77 0 019.49 0v37a4.77 4.77 0 01-9.49 0v-37zm23.73-.2a4.58 4.58 0 015-4.06 4.47 4.47 0 014.51 4.46l-2 37a4.57 4.57 0 01-5 4.06 4.47 4.47 0 01-4.51-4.46l2-37zM25 61.7a4.46 4.46 0 014.5-4.46 4.58 4.58 0 015 4.06l2 37a4.47 4.47 0 01-4.51 4.46 4.57 4.57 0 01-5-4.06l-2-37z', 'M11.17 37.16h83.48a8.4 8.4 0 012 .16 5.93 5.93 0 012.88 1.56 5.43 5.43 0 011.64 3.34 7.65 7.65 0 01-.06 1.44L94 117.31V117.72a7.06 7.06 0 01-.2.9v.06a5.89 5.89 0 01-5.47 4.07H17.32a6.17 6.17 0 01-1.25-.19 6.17 6.17 0 01-1.16-.48 6.18 6.18 0 01-3.08-4.88l-7-73.49a7.69 7.69 0 01-.06-1.66 5.37 5.37 0 011.63-3.29 6 6 0 013-1.58 8.94 8.94 0 011.79-.13zM5.65 8.8h31.47V6a2.44 2.44 0 010-.27 6 6 0 011.76-4A6 6 0 0143.09 0h19.67a6 6 0 015.7 6v2.8h32.39a4.7 4.7 0 014.31 4.43v10.36a2.59 2.59 0 01-2.59 2.59H2.59A2.59 2.59 0 010 23.62V13.53a1.56 1.56 0 010-.31 4.72 4.72 0 013.88-4.34 10.4 10.4 0 011.77-.08zm42.1 52.7a4.77 4.77 0 019.49 0v37a4.77 4.77 0 01-9.49 0v-37zm23.73-.2a4.58 4.58 0 015-4.06 4.47 4.47 0 014.51 4.46l-2 37a4.57 4.57 0 01-5 4.06 4.47 4.47 0 01-4.51-4.46l2-37zM25 61.7a4.46 4.46 0 014.5-4.46 4.58 4.58 0 015 4.06l2 37a4.47 4.47 0 01-4.51 4.46 4.57 4.57 0 01-5-4.06l-2-37z',
viewBox: '0 0 105.16 122.88', viewBox: '0 0 105.16 122.88',
ratio: 1, ratio: 1,
}, },
[SessionIconType.Delete3]: {
path:
'M4.873 9.058h33.35V6.187c0-.095.002-.186.014-.279.075-1.592.762-3.037 1.816-4.086l-.007-.007C41.15.711 42.683.025 44.371.009l.023.002V0H64.325c.106 0 .207.009.309.022 1.583.084 3.019.76 4.064 1.81 1.102 1.104 1.786 2.635 1.803 4.315l-.003.021h.014V9.057h32.926c.138 0 .268.014.401.034 1.182.106 2.254.625 3.034 1.41l.004.007.005-.007c.851.857 1.386 2.048 1.401 3.368l-.002.032h.014v10.861c0 1.472-1.195 2.665-2.667 2.665H2.667C1.195 27.426 0 26.233 0 24.762V13.919c0-.106.004-.211.018-.315v-.021c.089-1.207.624-2.304 1.422-3.098l-.007-.002c.862-.861 2.057-1.396 3.377-1.414l.032.002v-.013h.031zM77.79 49.097h-5.945v56.093h5.945V49.097zm-19.33 0h-5.948v56.093h5.948V49.097zm-19.33 0h-5.946v56.093h5.946V49.097zM10.837 31.569h87.385l.279.018.127.007.134.011h.009l.163.023c1.363.163 2.638.789 3.572 1.708 1.04 1.025 1.705 2.415 1.705 3.964 0 .098-.009.193-.019.286l-.002.068-.014.154-7.393 79.335-.007.043h.007l-.016.139-.051.283-.002.005-.002.018c-.055.331-.12.646-.209.928l-.007.022-.002.005-.009.018-.023.062-.004.021c-.118.354-.264.698-.432 1.009-1.009 1.88-2.879 3.187-5.204 3.187H18.13l-.247-.014v.003l-.011-.003-.032-.004c-.46-.023-.889-.091-1.288-.202-.415-.116-.818-.286-1.197-.495l-.009-.002-.002.002c-1.785-.977-2.975-2.882-3.17-5.022L4.88 37.79l-.011-.125-.011-.247-.004-.116h-.005c0-1.553.664-2.946 1.707-3.971.976-.955 2.32-1.599 3.756-1.726l.122-.004v-.007l.3-.013.104.002v-.014h-.001zm87.386 5.334H10.837v-.007l-.116.004c-.163.022-.322.106-.438.222-.063.063-.104.132-.104.179h-.007l.007.118 7.282 79.244h-.002l.002.012c.032.376.202.691.447.825l-.002.004.084.032.063.012H90.825c.207 0 .399-.157.518-.377l.084-.197.054-.216.014-.138h.005l7.384-79.21-.003-.11c0-.045-.041-.111-.103-.172-.12-.118-.286-.202-.451-.227l-.104.002zm.111-.002h-.016.016zm.549.512v-.004.004zm5.297.377l-.002.018.002-.018zM40.887 14.389H5.332v7.706h97.63v-7.706H67.844c-1.472 0-2.664-1.192-2.664-2.664V6.168h.007c-.007-.22-.106-.433-.259-.585-.137-.141-.324-.229-.521-.252H44.394v-.006c-.213.007-.422.104-.576.259l-.004-.004-.007.004c-.131.134-.231.313-.259.501l.007.102v5.537c-.001 1.472-1.196 2.665-2.668 2.665z',
viewBox: '0 0 108.294 122.88',
ratio: 1,
},
[SessionIconType.DoubleCheckCircleFilled]: { [SessionIconType.DoubleCheckCircleFilled]: {
path: path:
'M7.91731278,0.313257194 C6.15053376,1.58392424 5,3.65760134 5,6 C5,6.343797 5.0247846,6.68180525 5.07266453,7.01233547 L5,7.085 L3.205,5.295 L2.5,6 L5,8.5 L5.33970233,8.16029767 C5.80439817,9.59399486 6.71914823,10.8250231 7.91731278,11.6867428 C7.31518343,11.8898758 6.67037399,12 6,12 C2.688,12 0,9.312 0,6 C0,2.688 2.688,0 6,0 C6.67037399,0 7.31518343,0.110124239 7.91731278,0.313257194 Z M12,0 C15.312,0 18,2.688 18,6 C18,9.312 15.312,12 12,12 C8.688,12 6,9.312 6,6 C6,2.688 8.688,0 12,0 Z M11,8.5 L15.5,4 L14.795,3.29 L11,7.085 L9.205,5.295 L8.5,6 L11,8.5 Z', 'M7.91731278,0.313257194 C6.15053376,1.58392424 5,3.65760134 5,6 C5,6.343797 5.0247846,6.68180525 5.07266453,7.01233547 L5,7.085 L3.205,5.295 L2.5,6 L5,8.5 L5.33970233,8.16029767 C5.80439817,9.59399486 6.71914823,10.8250231 7.91731278,11.6867428 C7.31518343,11.8898758 6.67037399,12 6,12 C2.688,12 0,9.312 0,6 C0,2.688 2.688,0 6,0 C6.67037399,0 7.31518343,0.110124239 7.91731278,0.313257194 Z M12,0 C15.312,0 18,2.688 18,6 C18,9.312 15.312,12 12,12 C8.688,12 6,9.312 6,6 C6,2.688 8.688,0 12,0 Z M11,8.5 L15.5,4 L14.795,3.29 L11,7.085 L9.205,5.295 L8.5,6 L11,8.5 Z',

@ -3,7 +3,6 @@ import React from 'react';
// import 'reset-css/reset.css'; // import 'reset-css/reset.css';
import { DefaultTheme, ThemeProvider } from 'styled-components'; import { DefaultTheme, ThemeProvider } from 'styled-components';
import { pushToastWarning } from '../../session/utils/Toast';
const white = '#ffffff'; const white = '#ffffff';
const black = '#000000'; const black = '#000000';
@ -11,8 +10,10 @@ const warning = '#e7b100';
const destructive = '#ff453a'; const destructive = '#ff453a';
const accentLightTheme = '#00e97b'; const accentLightTheme = '#00e97b';
const accentDarkTheme = '#00f782'; const accentDarkTheme = '#00f782';
const borderLightTheme = '#f1f1f1'; const borderLightThemeColor = '#f1f1f1';
const borderDarkTheme = '#ffffff0F'; const borderDarkThemeColor = '#ffffff0F';
const borderHighContrastLightTheme = '#afafaf';
const borderHighContrastDarkTheme = '#484848';
const borderAvatarColor = '#00000059'; const borderAvatarColor = '#00000059';
const common = { const common = {
@ -55,6 +56,7 @@ export const lightTheme: DefaultTheme = {
textColorSubtleNoOpacity: '#52514f', textColorSubtleNoOpacity: '#52514f',
textColorOpposite: white, textColorOpposite: white,
textHighlight: `${black}33`, textHighlight: `${black}33`,
textAccent: '#00c769',
// inbox // inbox
inboxBackground: white, inboxBackground: white,
// buttons // buttons
@ -75,9 +77,12 @@ export const lightTheme: DefaultTheme = {
conversationItemHasUnread: '#fcfcfc', conversationItemHasUnread: '#fcfcfc',
conversationItemSelected: '#f0f0f0', conversationItemSelected: '#f0f0f0',
clickableHovered: '#dfdfdf', clickableHovered: '#dfdfdf',
sessionBorder: `1px solid ${borderLightTheme}`, sessionBorder: `1px solid ${borderLightThemeColor}`,
sessionBorderColor: borderLightThemeColor,
sessionBorderHighContrast: `1px solid ${borderHighContrastLightTheme}`,
sessionUnreadBorder: `4px solid ${accentLightTheme}`, sessionUnreadBorder: `4px solid ${accentLightTheme}`,
leftpaneOverlayBackground: white, leftpaneOverlayBackground: white,
recoveryPhraseBannerBackground: white,
// scrollbars // scrollbars
scrollBarTrack: '#fcfcfc', scrollBarTrack: '#fcfcfc',
scrollBarThumb: '#474646', scrollBarThumb: '#474646',
@ -111,6 +116,7 @@ export const darkTheme = {
textColorSubtleNoOpacity: '#7f7d7d', textColorSubtleNoOpacity: '#7f7d7d',
textColorOpposite: black, textColorOpposite: black,
textHighlight: `${accentDarkTheme}99`, textHighlight: `${accentDarkTheme}99`,
textAccent: accentDarkTheme,
// inbox // inbox
inboxBackground: 'linear-gradient(180deg, #171717 0%, #121212 100%)', inboxBackground: 'linear-gradient(180deg, #171717 0%, #121212 100%)',
// buttons // buttons
@ -131,9 +137,12 @@ export const darkTheme = {
conversationItemHasUnread: '#2c2c2c', conversationItemHasUnread: '#2c2c2c',
conversationItemSelected: '#404040', conversationItemSelected: '#404040',
clickableHovered: '#414347', clickableHovered: '#414347',
sessionBorder: `1px solid ${borderDarkTheme}`, sessionBorder: `1px solid ${borderDarkThemeColor}`,
sessionBorderColor: borderDarkThemeColor,
sessionBorderHighContrast: `1px solid ${borderHighContrastDarkTheme}`,
sessionUnreadBorder: `4px solid ${accentDarkTheme}`, sessionUnreadBorder: `4px solid ${accentDarkTheme}`,
leftpaneOverlayBackground: 'linear-gradient(180deg, #171717 0%, #121212 100%)', leftpaneOverlayBackground: 'linear-gradient(180deg, #171717 0%, #121212 100%)',
recoveryPhraseBannerBackground: '#1f1f1f',
// scrollbars // scrollbars
scrollBarTrack: '#1b1b1b', scrollBarTrack: '#1b1b1b',
scrollBarThumb: '#474646', scrollBarThumb: '#474646',

@ -6,10 +6,12 @@ import { createSlice } from '@reduxjs/toolkit';
export interface UserConfigState { export interface UserConfigState {
audioAutoplay: boolean; audioAutoplay: boolean;
showRecoveryPhrasePrompt: boolean;
} }
export const initialUserConfigState = { export const initialUserConfigState = {
audioAutoplay: false, audioAutoplay: false,
showRecoveryPhrasePrompt: true,
}; };
const userConfigSlice = createSlice({ const userConfigSlice = createSlice({
@ -19,9 +21,14 @@ const userConfigSlice = createSlice({
toggleAudioAutoplay: state => { toggleAudioAutoplay: state => {
state.audioAutoplay = !state.audioAutoplay; state.audioAutoplay = !state.audioAutoplay;
}, },
disableRecoveryPhrasePrompt: state => {
console.log('setting recovery phrase state');
state.showRecoveryPhrasePrompt = false
},
}, },
}); });
const { actions, reducer } = userConfigSlice; const { actions, reducer } = userConfigSlice;
export const { toggleAudioAutoplay } = actions; export const { toggleAudioAutoplay, disableRecoveryPhrasePrompt } = actions;
export const userConfigReducer = reducer; export const userConfigReducer = reducer;

@ -8,3 +8,9 @@ export const getAudioAutoplay = createSelector(
getUserConfig, getUserConfig,
(state: UserConfigState): boolean => state.audioAutoplay (state: UserConfigState): boolean => state.audioAutoplay
); );
export const getShowRecoveryPhrasePrompt = createSelector(
getUserConfig,
(state: UserConfigState): boolean => state.showRecoveryPhrasePrompt
);

4
ts/styled.d.ts vendored

@ -39,6 +39,7 @@ declare module 'styled-components' {
textColorSubtleNoOpacity: string; textColorSubtleNoOpacity: string;
textColorOpposite: string; textColorOpposite: string;
textHighlight: string; textHighlight: string;
textAccent: string;
// inbox // inbox
inboxBackground: string; inboxBackground: string;
// buttons // buttons
@ -60,8 +61,11 @@ declare module 'styled-components' {
conversationItemSelected: string; conversationItemSelected: string;
clickableHovered: string; clickableHovered: string;
sessionBorder: string; sessionBorder: string;
sessionBorderColor: string;
sessionBorderHighContrast: string;
sessionUnreadBorder: string; sessionUnreadBorder: string;
leftpaneOverlayBackground: string; leftpaneOverlayBackground: string;
recoveryPhraseBannerBackground: string;
// scrollbars // scrollbars
scrollBarTrack: string; scrollBarTrack: string;
scrollBarThumb: string; scrollBarThumb: string;

1
ts/window.d.ts vendored

@ -52,6 +52,7 @@ declare global {
}; };
lokiSnodeAPI: LokiSnodeAPI; lokiSnodeAPI: LokiSnodeAPI;
onLogin: any; onLogin: any;
persistStore?: Persistor;
resetDatabase: any; resetDatabase: any;
restart: any; restart: any;
getSeedNodeList: () => Array<any> | undefined; getSeedNodeList: () => Array<any> | undefined;

Loading…
Cancel
Save