add Dialog on app start to ask to update SessionID

pull/1404/head
Audric Ackermann 4 years ago
parent 1045bfeba8
commit b0a229bf13

@ -174,6 +174,7 @@
<script type='text/javascript' src='js/views/nickname_dialog_view.js'></script>
<script type='text/javascript' src='js/views/password_dialog_view.js'></script>
<script type='text/javascript' src='js/views/seed_dialog_view.js'></script>
<script type='text/javascript' src='js/views/session_id_reset_view.js'></script>
<!-- CRYPTO -->
<script type='text/javascript' src='js/wall_clock_listener.js'></script>

@ -555,6 +555,10 @@
confirmDialog.render();
};
window.showResetSessionIdDialog = () => {
appView.showResetSessionIdDialog();
};
window.showEditProfileDialog = async () => {
const ourNumber = window.storage.get('primaryDevicePubKey');
const conversation = await ConversationController.getOrCreateAndWait(

@ -39,6 +39,9 @@ const { SessionModal } = require('../../ts/components/session/SessionModal');
const {
SessionSeedModal,
} = require('../../ts/components/session/SessionSeedModal');
const {
SessionIDResetDialog,
} = require('../../ts/components/session/SessionIDResetDialog');
const {
SessionRegistrationView,
} = require('../../ts/components/session/SessionRegistrationView');
@ -77,7 +80,6 @@ const {
const {
GroupInvitation,
} = require('../../ts/components/conversation/GroupInvitation');
const { ConfirmDialog } = require('../../ts/components/ConfirmDialog');
const {
MediaGallery,
} = require('../../ts/components/conversation/media-gallery/MediaGallery');
@ -232,7 +234,6 @@ exports.setup = (options = {}) => {
UserDetailsDialog,
DevicePairingDialog,
SessionInboxView,
ConfirmDialog,
UpdateGroupNameDialog,
UpdateGroupMembersDialog,
InviteContactsDialog,
@ -243,6 +244,7 @@ exports.setup = (options = {}) => {
SessionConfirm,
SessionModal,
SessionSeedModal,
SessionIDResetDialog,
SessionPasswordModal,
SessionPasswordPrompt,
SessionRegistrationView,

@ -129,6 +129,12 @@
const dialog = new Whisper.EditProfileDialogView(options);
this.el.prepend(dialog.el);
},
showResetSessionIdDialog() {
const theme = this.getThemeObject();
const resetSessionIDDialog = new Whisper.SessionIDResetDialog({ theme });
this.el.prepend(resetSessionIDDialog.el);
},
showUserDetailsDialog(options) {
// eslint-disable-next-line no-param-reassign
options.theme = this.getThemeObject();

@ -33,6 +33,7 @@
unregisterEvents() {
document.removeEventListener('keyup', this.props.onClickClose, false);
this.$('.session-confirm-wrapper').remove();
},
render() {

@ -0,0 +1,35 @@
/* global Whisper */
// eslint-disable-next-line func-names
(function() {
'use strict';
window.Whisper = window.Whisper || {};
Whisper.SessionIDResetDialog = Whisper.View.extend({
className: 'loki-dialog session-id-reset-dialog modal',
initialize(options) {
this.close = this.close.bind(this);
this.theme = options.theme;
this.render();
},
render() {
this.dialogView = new Whisper.ReactWrapperView({
className: 'session-id-dialog-wrapper',
Component: window.Signal.Components.SessionIDResetDialog,
props: {
onClose: this.close,
theme: this.theme,
},
});
this.$el.append(this.dialogView.el);
return this;
},
close() {
this.remove();
},
});
})();

@ -426,7 +426,7 @@ label {
min-width: 300px;
box-sizing: border-box;
max-height: 70vh;
max-width: 70vw;
max-width: calc(min(70vw, 800px));
font-family: $session-font-default;
@include themify($themes) {
background-color: themed('modalBackground');
@ -508,6 +508,8 @@ label {
display: flex;
flex-direction: column;
align-items: center;
// to allow new lines
white-space: pre-wrap;
}
&__button-group {

@ -176,6 +176,7 @@
&-input-with-label-container {
height: 46.5px;
width: 280px;
font-family: $session-font-default;
@include themify($themes) {
color: themed('textColor');
}
@ -215,6 +216,7 @@
@include themify($themes) {
color: themed('textColor');
}
font-family: $session-font-default;
font-size: 12px;
line-height: 14px;
position: absolute;

@ -1,35 +0,0 @@
import React from 'react';
import { SessionModal } from './session/SessionModal';
import { SessionButton } from './session/SessionButton';
import { DefaultTheme } from 'styled-components';
type Props = {
titleText: string;
messageText: string;
okText: string;
cancelText: string;
onConfirm: any;
onClose: any;
theme: DefaultTheme;
};
export const ConfirmDialog = (props: Props) => {
return (
<SessionModal
title={props.titleText}
onClose={props.onClose}
onOk={() => null}
theme={props.theme}
>
<div className="spacer-md" />
<p className="messageText">{props.messageText}</p>
<div className="spacer-md" />
<div className="session-modal__button-group">
<SessionButton text={props.okText} onClick={props.onConfirm} />
<SessionButton text={props.cancelText} onClick={props.onClose} />
</div>
</SessionModal>
);
};

@ -12,6 +12,7 @@ import { DefaultTheme } from 'styled-components';
import { StateType } from '../../state/reducer';
import { MessageEncrypter } from '../../session/crypto';
import { PubKey } from '../../session/types';
import { UserUtil } from '../../util';
// tslint:disable-next-line: no-import-side-effect no-submodule-imports
export enum SectionType {
@ -49,6 +50,8 @@ class ActionsPanelPrivate extends React.Component<Props> {
const newThemeObject = theme === 'dark' ? darkTheme : lightTheme;
this.props.applyTheme(newThemeObject);
void this.showResetSessionIDDialogIfNeeded();
}
public Section = ({
@ -186,6 +189,14 @@ class ActionsPanelPrivate extends React.Component<Props> {
private readonly handleSectionSelect = (section: SectionType): void => {
this.props.onSectionSelected(section);
};
private async showResetSessionIDDialogIfNeeded() {
const userED25519KeyPairHex = await UserUtil.getUserED25519KeyPair();
if (userED25519KeyPairHex) {
return;
}
window.showResetSessionIdDialog();
}
}
const mapStateToProps = (state: StateType) => {

@ -5,7 +5,7 @@ import { SessionHtmlRenderer } from './SessionHTMLRenderer';
import { SessionIcon, SessionIconSize, SessionIconType } from './icon';
import { DefaultTheme, withTheme } from 'styled-components';
interface Props {
type Props = {
message: string;
messageSub: string;
title: string;
@ -21,96 +21,80 @@ interface Props {
sessionIcon?: SessionIconType;
iconSize?: SessionIconSize;
theme: DefaultTheme;
}
};
class SessionConfirmInner extends React.Component<Props> {
public static defaultProps = {
title: '',
messageSub: '',
okTheme: SessionButtonColor.Primary,
closeTheme: SessionButtonColor.Primary,
hideCancel: false,
};
const SessionConfirmInner = (props: Props) => {
const {
title = '',
message,
messageSub = '',
okTheme = SessionButtonColor.Primary,
closeTheme = SessionButtonColor.Primary,
onClickOk,
onClickClose,
hideCancel = false,
sessionIcon,
iconSize,
} = props;
constructor(props: any) {
super(props);
}
const okText = props.okText || window.i18n('ok');
const cancelText = props.cancelText || window.i18n('cancel');
const showHeader = !!props.title;
public render() {
const {
title,
message,
messageSub,
okTheme,
closeTheme,
onClickOk,
onClickClose,
hideCancel,
sessionIcon,
iconSize,
} = this.props;
const messageSubText = messageSub ? 'session-confirm-main-message' : 'subtle';
const okText = this.props.okText || window.i18n('ok');
const cancelText = this.props.cancelText || window.i18n('cancel');
const showHeader = !!this.props.title;
return (
<SessionModal
title={title}
onClose={onClickClose}
onOk={() => null}
showExitIcon={false}
showHeader={showHeader}
theme={props.theme}
>
{!showHeader && <div className="spacer-lg" />}
const messageSubText = messageSub
? 'session-confirm-main-message'
: 'subtle';
return (
<SessionModal
title={title}
onClose={onClickClose}
onOk={() => null}
showExitIcon={false}
showHeader={showHeader}
theme={this.props.theme}
>
{!showHeader && <div className="spacer-lg" />}
<div className="session-modal__centered">
{sessionIcon && iconSize && (
<>
<SessionIcon
iconType={sessionIcon}
iconSize={iconSize}
theme={props.theme}
/>
<div className="spacer-lg" />
</>
)}
<div className="session-modal__centered">
{sessionIcon && iconSize && (
<div>
<SessionIcon
iconType={sessionIcon}
iconSize={iconSize}
theme={this.props.theme}
/>
<div className="spacer-lg" />
</div>
)}
<SessionHtmlRenderer
tag="span"
className={messageSubText}
html={message}
/>
<SessionHtmlRenderer
tag="span"
className="session-confirm-sub-message subtle"
html={messageSub}
/>
</div>
<SessionHtmlRenderer
tag="span"
className={messageSubText}
html={message}
/>
<SessionHtmlRenderer
tag="span"
className="session-confirm-sub-message subtle"
html={messageSub}
/>
</div>
<div className="session-modal__button-group">
<SessionButton
text={okText}
buttonColor={okTheme}
onClick={onClickOk}
/>
<div className="session-modal__button-group">
{!hideCancel && (
<SessionButton
text={okText}
buttonColor={okTheme}
onClick={onClickOk}
text={cancelText}
buttonColor={closeTheme}
onClick={onClickClose}
/>
{!hideCancel && (
<SessionButton
text={cancelText}
buttonColor={closeTheme}
onClick={onClickClose}
/>
)}
</div>
</SessionModal>
);
}
}
)}
</div>
</SessionModal>
);
};
export const SessionConfirm = withTheme(SessionConfirmInner);

@ -0,0 +1,78 @@
import React, { useState } from 'react';
import { SessionModal } from './SessionModal';
import { SessionButton, SessionButtonColor } from './SessionButton';
import { DefaultTheme, withTheme } from 'styled-components';
import {
SessionIcon,
SessionIconButton,
SessionIconSize,
SessionIconType,
} from './icon';
type Props = {
onClose: any;
theme: DefaultTheme;
};
/* tslint:disable:use-simple-attributes */
const SessionIDResetDialogInner = (props: Props) => {
const [firstScreen, setFirstScreen] = useState(true);
const descFirst =
'Weve upgraded Session IDs to make them even more private and secure. We recommend upgrading to a new Session ID now.\n\n\
You will lose existing contacts and conversations, but youll gain even more privacy and security. You will need to upgrade your Session ID eventually, but you can choose to delay the upgrade if you need to save contacts or conversations.';
const descSecond =
'Youre upgrading to a new Session ID. This will give you improved privacy and security, but it will clear ALL app data. Contacts and conversations will be lost. Proceed?';
return (
<SessionModal
title={
(firstScreen && 'Session IDs Just Got Better') || 'Upgrade Session ID?'
}
onOk={() => null}
onClose={props.onClose}
theme={props.theme}
>
<div className="spacer-sm" />
<div className="session-modal__centered text-center">
{firstScreen && (
<SessionIcon
iconType={SessionIconType.Shield}
iconSize={SessionIconSize.Max}
theme={props.theme}
/>
)}
<div className="spacer-lg" />
{(firstScreen && descFirst) || descSecond}
<div className="spacer-xs" />
</div>
<div className="spacer-lg" />
<div className="session-modal__button-group">
<SessionButton
text={(firstScreen && 'Upgrade Now') || window.i18n('ok')}
onClick={() => {
if (firstScreen) {
setFirstScreen(false);
} else {
window.deleteAccount('Session ID Upgrade');
props.onClose();
}
}}
buttonColor={SessionButtonColor.Danger}
/>
<SessionButton
text={(firstScreen && 'Upgrade Later') || window.i18n('cancel')}
onClick={() => {
props.onClose();
}}
/>
</div>
</SessionModal>
);
};
export const SessionIDResetDialog = withTheme(SessionIDResetDialogInner);

@ -29,6 +29,7 @@ export enum SessionIconType {
Reply = 'reply',
Search = 'search',
Send = 'send',
Shield = 'shield',
Star = 'star',
Stopwatch = 'stopwatch',
Sun = 'sun',
@ -248,6 +249,12 @@ export const icons = {
viewBox: '0 0 22 21',
ratio: 1,
},
[SessionIconType.Shield]: {
path:
'M 349.875 62.773438 L 205.875 2.773438 C 197.015625 -0.898438 187.058594 -0.898438 178.199219 2.773438 L 34.199219 62.773438 C 20.773438 68.324219 12 81.449219 12 96 C 12 244.875 97.875 347.773438 178.125 381.226563 C 186.976563 384.898438 196.949219 384.898438 205.800781 381.226563 C 270.074219 354.449219 372 261.976563 372 96 C 372 81.449219 363.226563 68.324219 349.875 62.773438 Z M 192.074219 334.726563 L 192 48.976563 L 323.925781 103.949219 C 321.449219 217.5 262.351563 299.773438 192.074219 334.726563 Z M 192.074219 334.726563',
viewBox: '0 0 384 384',
ratio: 1,
},
[SessionIconType.Stopwatch]: {
path:
'm282.523438 1.34375c-8.800782-.886719-17.640626-1.328125-26.484376-1.3242188h-.265624c-14.636719.2421878-26.339844 12.2421878-26.214844 26.8828128v105.53125c-.035156 3.554687.6875 7.074218 2.117187 10.328125 4.582031 10.90625 15.863281 17.429687 27.597657 15.964843 13.554687-2.03125 23.5-13.792968 23.25-27.492187v-76.484375c98.890624 12.980469 173.726562 95.839844 176.59375 195.539062 2.867187 99.699219-67.078126 186.726563-165.058594 205.367188-97.980469 18.644531-195-36.613281-228.945313-130.398438-33.945312-93.785156 5.226563-198.339843 92.441407-246.730468 11.59375-6.566406 16.445312-20.769532 11.289062-33.054688l-.03125-.074218c-2.890625-6.988282-8.625-12.40625-15.765625-14.902344-7.136719-2.492188-15-1.820313-21.613281 1.84375-110.347656 61.484375-159.351563 194.269531-115.402344 312.695312 43.945312 118.429688 167.710938 187.097656 291.453125 161.710938 123.742187-25.386719 210.472656-137.238282 204.238281-263.40625-6.230468-126.164063-103.558594-228.925782-229.199218-241.996094zm0 0 M159.300781 170.949219c10.652344 28.050781 45.503907 94.28125 71.574219 122.480469 16.027344 18.09375 43.394531 20.515624 62.351562 5.523437 9.484376-7.957031 15.191407-19.527344 15.738282-31.894531.542968-12.363282-4.132813-24.390625-12.878906-33.148438-27.265626-27.261718-96.464844-63.382812-125.480469-74.398437-3.25-1.222657-6.917969-.417969-9.363281 2.050781-2.441407 2.472656-3.203126 6.148438-1.941407 9.386719zm0 0',

@ -79,7 +79,7 @@ const SessionSvg = (props: {
rotateDuration?: number;
theme: DefaultTheme;
}) => {
const colorSvg = props.iconColor || props?.theme?.colors.textColor || 'red';
const colorSvg = props.iconColor || props?.theme?.colors.textColor;
const pathArray = props.path instanceof Array ? props.path : [props.path];
return (

@ -218,9 +218,9 @@ async function decryptWithSessionProtocol(
// set the sender identity on the envelope itself.
if (isMediumGroup) {
envelope.senderIdentity = '05' + toHex(senderX25519PublicKey);
envelope.senderIdentity = `05${toHex(senderX25519PublicKey)}`;
}
return plaintext;
return unpad(plaintext);
}
function unpad(paddedData: ArrayBuffer): ArrayBuffer {

@ -3,6 +3,7 @@ import * as MessageEncrypter from './MessageEncrypter';
export { MessageEncrypter };
// libsodium-wrappers requires the `require` call to work
// tslint:disable-next-line: no-require-imports
import libsodiumwrappers = require('libsodium-wrappers');
export async function getSodium(): Promise<typeof libsodiumwrappers> {

1
ts/window.d.ts vendored

@ -86,6 +86,7 @@ declare global {
setSettingValue: any;
shortenPubkey: (pubKey: string) => string;
showEditProfileDialog: any;
showResetSessionIdDialog: any;
storage: any;
textsecure: LibTextsecure;
toggleLinkPreview: any;

Loading…
Cancel
Save