diff --git a/_locales/en/messages.json b/_locales/en/messages.json
index 442a633ef..cbfa1aab0 100644
--- a/_locales/en/messages.json
+++ b/_locales/en/messages.json
@@ -426,5 +426,12 @@
"dialogClearAllDataDeletionFailedMultiple": "Data not deleted by those Service Nodes: $snodes$",
"dialogClearAllDataDeletionQuestion": "Would you like to clear only this device, or delete your entire account?",
"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!"
}
diff --git a/ts/components/dialog/DeleteAccountModal.tsx b/ts/components/dialog/DeleteAccountModal.tsx
index b0e948019..40c4226f5 100644
--- a/ts/components/dialog/DeleteAccountModal.tsx
+++ b/ts/components/dialog/DeleteAccountModal.tsx
@@ -11,6 +11,7 @@ import { SessionWrapperModal } from '../session/SessionWrapperModal';
const deleteDbLocally = async () => {
window?.log?.info('configuration message sent successfully. Deleting everything');
+ window.persistStore?.purge();
await window.Signal.Logs.deleteAll();
await window.Signal.Data.removeAll();
await window.Signal.Data.close();
diff --git a/ts/components/session/LeftPaneSectionHeader.tsx b/ts/components/session/LeftPaneSectionHeader.tsx
index b72d95285..9d32acdf6 100644
--- a/ts/components/session/LeftPaneSectionHeader.tsx
+++ b/ts/components/session/LeftPaneSectionHeader.tsx
@@ -1,8 +1,13 @@
-import React from 'react';
+import React, { useState } from 'react';
import classNames from 'classnames';
import { SessionIcon, SessionIconSize, SessionIconType } from './icon';
-import { DefaultTheme, useTheme } from 'styled-components';
-import { SessionButton } from './SessionButton';
+import styled, { DefaultTheme, useTheme } from 'styled-components';
+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 = ({
isSelected,
@@ -17,8 +22,8 @@ const Tab = ({
}) => {
const handleClick = onSelect
? () => {
- onSelect(type);
- }
+ onSelect(type);
+ }
: undefined;
return (
@@ -40,22 +45,232 @@ type Props = {
export const LeftPaneSectionHeader = (props: Props) => {
const { label, buttonIcon, buttonClicked } = props;
-
const theme = useTheme();
+ const showRecoveryPhrasePrompt = useSelector(getShowRecoveryPhrasePrompt);
return (
-
- {label && }
- {buttonIcon && (
-
-
-
- )}
-
+
+
+ {label && }
+ {buttonIcon && (
+
+
+
+ )}
+
+ {showRecoveryPhrasePrompt && }
+
);
};
+
+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 (
+
+
+ {bodyText}
+
+ {!recoveryPhraseHidden &&
+
+ {recoveryPhrase}
+
+ }
+ {!isCompleted &&
+
+ }
+
+ )
+ }
+
+ const useColumn = completion === 90 && handleShowRecoveryClick;
+ const theme = useTheme();
+
+ return (
+
+
+
+
+
+ {bannerTitle} {completionText}
+
+
+
+
+
+ )
+}
+
+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;
+`;
diff --git a/ts/components/session/LeftPaneSettingSection.tsx b/ts/components/session/LeftPaneSettingSection.tsx
index fb71e90c2..4f6617089 100644
--- a/ts/components/session/LeftPaneSettingSection.tsx
+++ b/ts/components/session/LeftPaneSettingSection.tsx
@@ -1,4 +1,4 @@
-import React, { useState } from 'react';
+import React from 'react';
import classNames from 'classnames';
import { SessionButton, SessionButtonColor, SessionButtonType } from './SessionButton';
@@ -13,6 +13,12 @@ import { getFocusedSettingsSection } from '../../state/selectors/section';
import { getTheme } from '../../state/selectors/theme';
import { recoveryPhraseModal, updateDeleteAccountModal } from '../../state/ducks/modalDialog';
+type Props = {
+ settingsCategory: SessionSettingCategory;
+ showSettingsSection: (category: SessionSettingCategory) => void;
+ theme: DefaultTheme;
+};
+
const getCategories = () => {
return [
{
diff --git a/ts/components/session/SessionInboxView.tsx b/ts/components/session/SessionInboxView.tsx
index 9357b30bc..defd3845b 100644
--- a/ts/components/session/SessionInboxView.tsx
+++ b/ts/components/session/SessionInboxView.tsx
@@ -52,6 +52,7 @@ export class SessionInboxView extends React.Component {
}
const persistor = persistStore(this.store);
+ window.persistStore = persistor;
return (
diff --git a/ts/components/session/conversation/SessionRecording.tsx b/ts/components/session/conversation/SessionRecording.tsx
index 58d8a2059..94d3a9beb 100644
--- a/ts/components/session/conversation/SessionRecording.tsx
+++ b/ts/components/session/conversation/SessionRecording.tsx
@@ -3,12 +3,11 @@ import classNames from 'classnames';
import moment from 'moment';
import { SessionIconButton, SessionIconSize, SessionIconType } from '../icon';
-import { SessionButton, SessionButtonColor, SessionButtonType } from '../SessionButton';
import { Constants } from '../../../session';
import { ToastUtils } from '../../../session/utils';
import autoBind from 'auto-bind';
import MicRecorder from 'mic-recorder-to-mp3';
-import styled, { useTheme } from 'styled-components';
+import styled from 'styled-components';
interface Props {
onExitVoiceNoteView: any;
@@ -164,7 +163,7 @@ class SessionRecordingInner extends React.Component {
)}
{hasRecording && (
@@ -366,7 +365,6 @@ class SessionRecordingInner extends React.Component {
const audioURL = window.URL.createObjectURL(this.audioBlobMp3);
this.audioElement = new Audio(audioURL);
- // ww adding record duration
this.setState({
recordDuration: this.audioElement.duration,
});
diff --git a/ts/components/session/icon/Icons.tsx b/ts/components/session/icon/Icons.tsx
index fc18eff79..c95a62543 100644
--- a/ts/components/session/icon/Icons.tsx
+++ b/ts/components/session/icon/Icons.tsx
@@ -13,8 +13,6 @@ export enum SessionIconType {
CircleElipses = 'circleElipses',
Contacts = 'contacts',
Delete = 'delete',
- Delete2 = 'delete2',
- Delete3 = 'delete3',
Ellipses = 'ellipses',
Emoji = 'emoji',
Error = 'error',
@@ -130,23 +128,11 @@ export const icons = {
ratio: 1,
},
[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:
'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',
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]: {
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',
diff --git a/ts/state/ducks/SessionTheme.tsx b/ts/state/ducks/SessionTheme.tsx
index 6a4c43f93..575a8ce0a 100644
--- a/ts/state/ducks/SessionTheme.tsx
+++ b/ts/state/ducks/SessionTheme.tsx
@@ -3,7 +3,6 @@ import React from 'react';
// import 'reset-css/reset.css';
import { DefaultTheme, ThemeProvider } from 'styled-components';
-import { pushToastWarning } from '../../session/utils/Toast';
const white = '#ffffff';
const black = '#000000';
@@ -11,8 +10,10 @@ const warning = '#e7b100';
const destructive = '#ff453a';
const accentLightTheme = '#00e97b';
const accentDarkTheme = '#00f782';
-const borderLightTheme = '#f1f1f1';
-const borderDarkTheme = '#ffffff0F';
+const borderLightThemeColor = '#f1f1f1';
+const borderDarkThemeColor = '#ffffff0F';
+const borderHighContrastLightTheme = '#afafaf';
+const borderHighContrastDarkTheme = '#484848';
const borderAvatarColor = '#00000059';
const common = {
@@ -55,6 +56,7 @@ export const lightTheme: DefaultTheme = {
textColorSubtleNoOpacity: '#52514f',
textColorOpposite: white,
textHighlight: `${black}33`,
+ textAccent: '#00c769',
// inbox
inboxBackground: white,
// buttons
@@ -75,9 +77,12 @@ export const lightTheme: DefaultTheme = {
conversationItemHasUnread: '#fcfcfc',
conversationItemSelected: '#f0f0f0',
clickableHovered: '#dfdfdf',
- sessionBorder: `1px solid ${borderLightTheme}`,
+ sessionBorder: `1px solid ${borderLightThemeColor}`,
+ sessionBorderColor: borderLightThemeColor,
+ sessionBorderHighContrast: `1px solid ${borderHighContrastLightTheme}`,
sessionUnreadBorder: `4px solid ${accentLightTheme}`,
leftpaneOverlayBackground: white,
+ recoveryPhraseBannerBackground: white,
// scrollbars
scrollBarTrack: '#fcfcfc',
scrollBarThumb: '#474646',
@@ -111,6 +116,7 @@ export const darkTheme = {
textColorSubtleNoOpacity: '#7f7d7d',
textColorOpposite: black,
textHighlight: `${accentDarkTheme}99`,
+ textAccent: accentDarkTheme,
// inbox
inboxBackground: 'linear-gradient(180deg, #171717 0%, #121212 100%)',
// buttons
@@ -131,9 +137,12 @@ export const darkTheme = {
conversationItemHasUnread: '#2c2c2c',
conversationItemSelected: '#404040',
clickableHovered: '#414347',
- sessionBorder: `1px solid ${borderDarkTheme}`,
+ sessionBorder: `1px solid ${borderDarkThemeColor}`,
+ sessionBorderColor: borderDarkThemeColor,
+ sessionBorderHighContrast: `1px solid ${borderHighContrastDarkTheme}`,
sessionUnreadBorder: `4px solid ${accentDarkTheme}`,
leftpaneOverlayBackground: 'linear-gradient(180deg, #171717 0%, #121212 100%)',
+ recoveryPhraseBannerBackground: '#1f1f1f',
// scrollbars
scrollBarTrack: '#1b1b1b',
scrollBarThumb: '#474646',
diff --git a/ts/state/ducks/userConfig.tsx b/ts/state/ducks/userConfig.tsx
index 1c704e2b4..20316fcdf 100644
--- a/ts/state/ducks/userConfig.tsx
+++ b/ts/state/ducks/userConfig.tsx
@@ -6,10 +6,12 @@ import { createSlice } from '@reduxjs/toolkit';
export interface UserConfigState {
audioAutoplay: boolean;
+ showRecoveryPhrasePrompt: boolean;
}
export const initialUserConfigState = {
audioAutoplay: false,
+ showRecoveryPhrasePrompt: true,
};
const userConfigSlice = createSlice({
@@ -19,9 +21,14 @@ const userConfigSlice = createSlice({
toggleAudioAutoplay: state => {
state.audioAutoplay = !state.audioAutoplay;
},
+ disableRecoveryPhrasePrompt: state => {
+ console.log('setting recovery phrase state');
+ state.showRecoveryPhrasePrompt = false
+ },
+
},
});
const { actions, reducer } = userConfigSlice;
-export const { toggleAudioAutoplay } = actions;
+export const { toggleAudioAutoplay, disableRecoveryPhrasePrompt } = actions;
export const userConfigReducer = reducer;
diff --git a/ts/state/selectors/userConfig.ts b/ts/state/selectors/userConfig.ts
index 084f8d9ac..1e3de4c7c 100644
--- a/ts/state/selectors/userConfig.ts
+++ b/ts/state/selectors/userConfig.ts
@@ -8,3 +8,9 @@ export const getAudioAutoplay = createSelector(
getUserConfig,
(state: UserConfigState): boolean => state.audioAutoplay
);
+
+
+export const getShowRecoveryPhrasePrompt = createSelector(
+ getUserConfig,
+ (state: UserConfigState): boolean => state.showRecoveryPhrasePrompt
+);
diff --git a/ts/styled.d.ts b/ts/styled.d.ts
index 905375e34..953f901d3 100644
--- a/ts/styled.d.ts
+++ b/ts/styled.d.ts
@@ -39,6 +39,7 @@ declare module 'styled-components' {
textColorSubtleNoOpacity: string;
textColorOpposite: string;
textHighlight: string;
+ textAccent: string;
// inbox
inboxBackground: string;
// buttons
@@ -60,8 +61,11 @@ declare module 'styled-components' {
conversationItemSelected: string;
clickableHovered: string;
sessionBorder: string;
+ sessionBorderColor: string;
+ sessionBorderHighContrast: string;
sessionUnreadBorder: string;
leftpaneOverlayBackground: string;
+ recoveryPhraseBannerBackground: string;
// scrollbars
scrollBarTrack: string;
scrollBarThumb: string;
diff --git a/ts/window.d.ts b/ts/window.d.ts
index c4a8c17ea..2ba243d01 100644
--- a/ts/window.d.ts
+++ b/ts/window.d.ts
@@ -52,6 +52,7 @@ declare global {
};
lokiSnodeAPI: LokiSnodeAPI;
onLogin: any;
+ persistStore?: Persistor;
resetDatabase: any;
restart: any;
getSeedNodeList: () => Array | undefined;