Merge pull request #716 from vincentbavitz/brand-redesign

Modal tinkering and improvements
pull/737/head
Vince 5 years ago committed by GitHub
commit 144a99b6fb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -2021,7 +2021,7 @@
},
"copyPublicKey": {
"message": "Copy public key",
"message": "Copy Public Key",
"description":
"Button action that the user can click to copy their public keys"
},
@ -2086,7 +2086,7 @@
"A toast message telling the user that the message text was copied"
},
"editProfile": {
"message": "Edit profile",
"message": "Edit Profile",
"description": "Button action that the user can click to edit their profile"
},
@ -2102,16 +2102,40 @@
},
"showSeed": {
"message": "Show seed",
"message": "Show Seed",
"description":
"Button action that the user can click to view their unique seed"
},
"showSeedPasswordRequest": {
"message": "Please enter your password",
"description": "Request for user to enter password to show seed."
},
"seedSavePromptMain": {
"message": "Please save the seed below in a safe location.",
"description":
"Prompt on seed modal requesting user to save their seed. Line one"
},
"seedSavePromptAlt": {
"message":
"They can be used to restore your account if you lose access or migrate to a new device.",
"description":
"Prompt on seed modal requesting user to save their seed. Line two"
},
"QRCodeTitle": {
"message": "View My QR Code",
"description": "Title given to QR Code modal"
},
"QRCodeDescription": {
"message":
"This is <strong>your unique public QR Code.</strong><br/>Other users may scan this in order to begin a conversation with you.",
"description": "Description given to QRCode modal"
},
"showQRCode": {
"message": "Show QR code",
"message": "Show QR Code",
"description": "Button action that the user can click to view their QR code"
},
"showAddServer": {
"message": "Add public server",
"message": "Add Public Server",
"description":
"Button action that the user can click to connect to a new public server"
},
@ -2160,7 +2184,10 @@
"description":
"A button action that the user can click to reset the database"
},
"password": {
"message": "Password",
"description": "Placeholder for password input"
},
"setPassword": {
"message": "Set Password",
"description": "Button action that the user can click to set a password"
@ -2182,6 +2209,9 @@
"invalidPassword": {
"message": "Invalid password"
},
"noGivenPassword": {
"message": "Please enter your password"
},
"passwordsDoNotMatch": {
"message": "Passwords do not match"
},

@ -60,9 +60,16 @@ const {
const { SessionToast } = require('../../ts/components/session/SessionToast');
const { SessionToggle } = require('../../ts/components/session/SessionToggle');
const { SessionModal } = require('../../ts/components/session/SessionModal');
const {
SessionQRModal,
} = require('../../ts/components/session/SessionQRModal');
const {
SessionSeedModal,
} = require('../../ts/components/session/SessionSeedModal');
const {
SessionConfirm,
} = require('../../ts/components/session/SessionConfirm');
const {
SessionDropdown,
} = require('../../ts/components/session/SessionDropdown');
@ -270,6 +277,8 @@ exports.setup = (options = {}) => {
SessionToggle,
SessionConfirm,
SessionModal,
SessionQRModal,
SessionSeedModal,
SessionDropdown,
MediaGallery,
Message,

@ -196,8 +196,8 @@
this.el.append(dialog.el);
dialog.focusInput();
},
showPasswordDialog({ type, resolve, reject }) {
const dialog = Whisper.getPasswordDialogView(type, resolve, reject);
showPasswordDialog() {
const dialog = Whisper.PasswordDialogView();
this.el.append(dialog.el);
},
showSeedDialog(seed) {
@ -205,7 +205,9 @@
this.el.append(dialog.el);
},
showQRDialog(string) {
const dialog = new Whisper.QRDialogView({ string });
const dialog = new Whisper.QRDialogView({
value: string,
});
this.el.append(dialog.el);
},
showDevicePairingDialog() {

@ -1,4 +1,4 @@
/* global Whisper, i18n, QRCode */
/* global Whisper */
// eslint-disable-next-line func-names
(function() {
@ -7,41 +7,30 @@
window.Whisper = window.Whisper || {};
Whisper.QRDialogView = Whisper.View.extend({
templateName: 'qr-code-template',
className: 'loki-dialog qr-dialog modal',
initialize(options = {}) {
this.okText = options.okText || i18n('ok');
this.render();
this.$('.qr-dialog').bind('keyup', event => this.onKeyup(event));
initialize(options) {
this.value = options.value || '';
this.close = this.close.bind(this);
if (options.string) {
this.qr = new QRCode(this.$('#qr')[0], {
correctLevel: QRCode.CorrectLevel.L,
}).makeCode(options.string);
this.$('#qr').addClass('ready');
}
},
events: {
'click .ok': 'close',
this.render();
},
render_attributes() {
return {
ok: this.okText,
};
render() {
this.dialogView = new Whisper.ReactWrapperView({
className: 'qr-dialog-wrapper',
Component: window.Signal.Components.SessionQRModal,
props: {
value: this.value,
onClose: this.close,
},
});
this.$el.append(this.dialogView.el);
return this;
},
close() {
this.remove();
},
onKeyup(event) {
switch (event.key) {
case 'Enter':
case 'Escape':
case 'Esc':
this.close();
break;
default:
break;
}
},
});
})();

@ -1,4 +1,4 @@
/* global Whisper, i18n, Signal, passwordUtil */
/* global Whisper */
// eslint-disable-next-line func-names
(function() {
@ -8,90 +8,26 @@
Whisper.SeedDialogView = Whisper.View.extend({
className: 'loki-dialog seed-dialog modal',
templateName: 'seed-dialog',
initialize(options = {}) {
this.okText = options.okText || i18n('ok');
this.cancelText = options.cancelText || i18n('cancel');
this.confirmText = options.confirmText || i18n('confirm');
this.copyText = options.copyText || i18n('copySeed');
this.seed = options.seed || '-';
initialize() {
this.close = this.close.bind(this);
this.render();
this.showSeedView(false);
this.initPasswordHash();
this.$('#password').bind('keyup', event => this.onKeyup(event));
},
events: {
'click .ok': 'close',
'click .confirm': 'confirmPassword',
'click .copy-seed': 'copySeed',
},
render_attributes() {
return {
passwordViewTitle: i18n('passwordViewTitle'),
seedViewTitle: i18n('seedViewTitle'),
ok: this.okText,
copyText: this.copyText,
confirm: this.confirmText,
cancel: this.cancelText,
};
},
async initPasswordHash() {
const hash = await Signal.Data.getPasswordHash();
this.passwordHash = hash;
this.showSeedView(!hash);
},
showSeedView(show) {
const seedView = this.$('.seedView');
const passwordView = this.$('.passwordView');
if (show) {
this.$('.seed').html(this.seed);
seedView.show();
passwordView.hide();
} else {
this.$('.seed').html('');
passwordView.show();
this.$('#password').focus();
seedView.hide();
}
},
confirmPassword() {
this.$('.error').html();
const password = this.$('#password').val();
if (
this.passwordHash &&
!passwordUtil.matchesHash(password, this.passwordHash)
) {
this.$('.error').html(`Error: ${i18n('invalidPassword')}`);
return;
}
this.showSeedView(true);
render() {
this.dialogView = new Whisper.ReactWrapperView({
className: 'seed-dialog-wrapper',
Component: window.Signal.Components.SessionSeedModal,
props: {
onClose: this.close,
},
});
this.$el.append(this.dialogView.el);
return this;
},
close() {
this.remove();
},
copySeed() {
window.clipboard.writeText(this.seed);
window.pushToast({
title: i18n('copiedMnemonic'),
type: 'success',
id: 'copySeedToast',
});
},
onKeyup(event) {
switch (event.key) {
case 'Enter':
this.confirmPassword();
break;
case 'Escape':
case 'Esc':
this.close();
break;
default:
break;
}
},
});
})();

@ -1,32 +0,0 @@
/* global Whisper */
// eslint-disable-next-line func-names
(function() {
'use strict';
window.Whisper = window.Whisper || {};
Whisper.SessionDropdownView = Whisper.View.extend({
initialize(options) {
this.props = {
items: options.items,
};
this.render();
},
render() {
this.dropdownView = new Whisper.ReactWrapperView({
className: 'session-dropdown-wrapper',
Component: window.Signal.Components.SessionDropdown,
props: this.props,
});
this.$el.append(this.dropdownView.el);
},
openDropdown() {},
closeDropdown() {},
});
})();

@ -101,12 +101,11 @@
"pify": "3.0.0",
"protobufjs": "6.8.6",
"proxy-agent": "3.0.3",
"qrcode": "^1.4.4",
"react": "16.8.3",
"react-contextmenu": "2.11.0",
"react-dom": "16.8.3",
"react-portal": "^4.2.0",
"react-qrcode": "^0.2.0",
"react-qr-svg": "^2.2.1",
"react-redux": "6.0.1",
"react-virtualized": "9.21.0",
"read-last-lines": "1.3.0",

@ -109,6 +109,17 @@ div.spacer-lg {
opacity: 0.4;
}
.text-center {
text-align: center;
}
@mixin text-highlight($color) {
background-color: rgba($color, 0.4);
padding: $session-margin-xs;
border-radius: 3px;
display: inline-block;
}
.fullwidth {
width: 100%;
}
@ -129,6 +140,10 @@ $session-icon-size-sm: 15px;
$session-icon-size-md: 20px;
$session-icon-size-lg: 30px;
$session-modal-size-sm: 220px;
$session-modal-size-md: 400px;
$session-modal-size-lg: 650px;
$session-conversation-header-height: 60px;
@mixin fontWasaBold {
@ -513,12 +528,18 @@ label {
}
}
.user-details-dialog {
.message {
word-break: break-all;
}
}
#session-toast-container {
position: fixed;
right: $session-margin-lg;
bottom: $session-margin-lg;
z-index: 100;
z-index: 10000;
}
.session-toast {
@ -600,6 +621,7 @@ label {
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
min-width: 300px;
box-sizing: border-box;
max-height: 70vh;
@ -670,6 +692,10 @@ label {
margin: 0 $session-margin-xs;
}
}
&__text-highlight {
@include text-highlight($session-shade-15);
}
}
.session-toggle {
@ -850,6 +876,27 @@ label {
}
}
#qr svg {
width: $session-modal-size-sm;
height: $session-modal-size-sm;
border-radius: 3px;
}
.qr-dialog {
&__description {
max-width: $session-modal-size-sm;
text-align: center;
margin: 0 auto;
}
}
.seed-dialog {
&__description {
max-width: $session-modal-size-lg;
}
.messages li {
transition: $session-transition-duration !important;
}

@ -36,7 +36,9 @@ export class AddServerDialog extends React.Component<Props, State> {
this.attemptConnection = this.attemptConnection.bind(this);
this.closeDialog = this.closeDialog.bind(this);
this.onKeyUp = this.onKeyUp.bind(this);
this.onEnter = this.onEnter.bind(this);
window.addEventListener('keyup', this.onEnter);
}
public render() {
@ -55,7 +57,7 @@ export class AddServerDialog extends React.Component<Props, State> {
<input
type="text"
id="server-url"
placeholder={i18n('serverURL')}
placeholder={i18n('serverUrl')}
defaultValue={this.state.serverURL}
/>
<div className="spacer-sm" />
@ -191,23 +193,16 @@ export class AddServerDialog extends React.Component<Props, State> {
);
}
private onKeyUp(event: any) {
switch (event.key) {
case 'Enter':
if (this.state.view === 'default') {
this.showView('connecting');
}
break;
case 'Esc':
case 'Escape':
this.closeDialog();
break;
default:
private onEnter(event: any) {
if (event.key === 'Enter') {
if ($('#server-url').is(':focus')) {
this.showView('connecting');
}
}
}
private closeDialog() {
window.removeEventListener('keyup', this.onKeyUp);
window.removeEventListener('keyup', this.onEnter);
this.props.onClose();
}
@ -217,7 +212,7 @@ export class AddServerDialog extends React.Component<Props, State> {
const rawserverURL = serverURL
.replace(/^https?:\/\//i, '')
.replace(/[/\\]+$/i, '');
const sslserverURL = `https://${rawserverURL}`;
const sslServerURL = `https://${rawserverURL}`;
const conversationId = `publicChat:${channelId}@${rawserverURL}`;
const conversationExists = window.ConversationController.get(
@ -231,7 +226,7 @@ export class AddServerDialog extends React.Component<Props, State> {
}
const serverAPI = await window.lokiPublicChatAPI.findOrCreateServer(
sslserverURL
sslServerURL
);
if (!serverAPI) {
// Url incorrect or server not compatible
@ -246,7 +241,7 @@ export class AddServerDialog extends React.Component<Props, State> {
);
await serverAPI.findOrCreateChannel(channelId, conversationId);
await conversation.setPublicSource(sslserverURL, channelId);
await conversation.setPublicSource(sslServerURL, channelId);
await conversation.setFriendRequestStatus(
window.friends.friendRequestStatusEnum.friends
);

@ -1,5 +1,5 @@
import React from 'react';
import { QRCode } from 'react-qrcode';
import { QRCode } from 'react-qr-svg';
import { SessionModal } from './session/SessionModal';
import { SessionButton } from './session/SessionButton';
@ -59,23 +59,29 @@ export class DevicePairingDialog extends React.Component<Props, State> {
const waitingForRequest = this.state.view === 'waitingForRequest';
const nothingPaired = this.state.data.length === 0;
const renderPairedDevices = this.state.data.map((pubKey: any) => {
const pubKeyInfo = this.getPubkeyName(pubKey);
const isFinalItem =
this.state.data[this.state.data.length - 1] === pubKey;
return (
<div key={pubKey}>
<p>
{pubKeyInfo.deviceAlias}
<br />
<span className="text-subtle">Pairing Secret:</span>{' '}
{pubKeyInfo.secretWords}
</p>
{!isFinalItem ? <hr className="text-soft fullwidth" /> : null}
</div>
);
});
const theme = window.Events.getThemeSetting();
// Foreground equivalent to .session-modal background color
const bgColor = 'rgba(0, 0, 0, 0)';
const fgColor = theme === 'dark' ? '#FFFFFF' : '#1B1B1B';
// const renderPairedDevices = this.state.data.map((pubKey: any) => {
// const pubKeyInfo = this.getPubkeyName(pubKey);
// const isFinalItem =
// this.state.data[this.state.data.length - 1] === pubKey;
// return (
// <div key={pubKey}>
// <p>
// {pubKeyInfo.deviceAlias}
// <br />
// <span className="text-subtle">Pairing Secret:</span>{' '}
// {pubKeyInfo.secretWords}
// </p>
// {!isFinalItem ? <hr className="text-soft fullwidth" /> : null}
// </div>
// );
// });
return (
<>
@ -94,7 +100,12 @@ export class DevicePairingDialog extends React.Component<Props, State> {
<div className="spacer-lg" />
<div id="qr">
<QRCode value={window.textsecure.storage.user.getNumber()} />
<QRCode
value={window.textsecure.storage.user.getNumber()}
bgColor={bgColor}
fgColor={fgColor}
level="L"
/>
</div>
<div className="spacer-lg" />
@ -113,7 +124,7 @@ export class DevicePairingDialog extends React.Component<Props, State> {
</div>
) : (
<div className="session-modal__centered">
{renderPairedDevices}
{'renderPairedDevices'}
</div>
)}
@ -202,58 +213,58 @@ export class DevicePairingDialog extends React.Component<Props, State> {
this.showView();
}
private requestReceived(secondaryDevicePubKey: string | EventHandlerNonNull) {
// FIFO: push at the front of the array with unshift()
this.state.pubKeyRequests.unshift(secondaryDevicePubKey);
if (!this.state.currentPubKey) {
this.nextPubKey();
this.showView('requestReceived');
}
}
private allowDevice() {
this.setState({
accepted: true,
});
window.Whisper.trigger(
'devicePairingRequestAccepted',
this.state.currentPubKey,
(errors: any) => {
this.transmisssionCB(errors);
return true;
}
);
this.showView();
}
private transmisssionCB(errors: any) {
if (!errors) {
this.setState({
success: true,
});
} else {
return;
}
}
private skipDevice() {
window.Whisper.trigger(
'devicePairingRequestRejected',
this.state.currentPubKey
);
this.nextPubKey();
this.showView();
}
private nextPubKey() {
// FIFO: pop at the back of the array using pop()
const pubKeyRequests = this.state.pubKeyRequests;
this.setState({
currentPubKey: pubKeyRequests.pop(),
});
}
// private requestReceived(secondaryDevicePubKey: string | EventHandlerNonNull) {
// // FIFO: push at the front of the array with unshift()
// this.state.pubKeyRequests.unshift(secondaryDevicePubKey);
// if (!this.state.currentPubKey) {
// this.nextPubKey();
// this.showView('requestReceived');
// }
// }
// private allowDevice() {
// this.setState({
// accepted: true,
// });
// window.Whisper.trigger(
// 'devicePairingRequestAccepted',
// this.state.currentPubKey,
// (errors: any) => {
// this.transmisssionCB(errors);
// return true;
// }
// );
// this.showView();
// }
// private transmisssionCB(errors: any) {
// if (!errors) {
// this.setState({
// success: true,
// });
// } else {
// return;
// }
// }
// private skipDevice() {
// window.Whisper.trigger(
// 'devicePairingRequestRejected',
// this.state.currentPubKey
// );
// this.nextPubKey();
// this.showView();
// }
// private nextPubKey() {
// // FIFO: pop at the back of the array using pop()
// const pubKeyRequests = this.state.pubKeyRequests;
// this.setState({
// currentPubKey: pubKeyRequests.pop(),
// });
// }
private onKeyUp(event: any) {
switch (event.key) {

@ -3,12 +3,7 @@ import React from 'react';
import { ContactName } from './ContactName';
import { Avatar } from '../Avatar';
import { Colors, LocalizerType } from '../../types/Util';
import {
ContextMenu,
//ContextMenuTrigger,
MenuItem,
SubMenu,
} from 'react-contextmenu';
import { ContextMenu, MenuItem, SubMenu } from 'react-contextmenu';
import {
SessionIconButton,
@ -22,8 +17,6 @@ import {
SessionButtonType,
} from '../session/SessionButton';
import { SessionDropdownTrigger } from '../session/SessionDropdownTrigger';
interface TimerOption {
name: string;
value: number;
@ -239,21 +232,20 @@ export class ConversationHeader extends React.Component<Props> {
);
}
public renderOptions(triggerId: string) {
public renderOptions() {
const { showBackButton } = this.props;
console.log('FIXME:', triggerId);
if (showBackButton) {
return null;
}
return (
<SessionDropdownTrigger>
<>
<SessionIconButton
iconType={SessionIconType.Ellipses}
iconSize={SessionIconSize.Large}
/>
</SessionDropdownTrigger>
</>
);
}
@ -344,7 +336,7 @@ export class ConversationHeader extends React.Component<Props> {
{this.renderBackButton()}
<div className="module-conversation-header__title-container">
<div className="module-conversation-header__title-flex">
{this.renderOptions(triggerId)}
{this.renderOptions()}
{this.renderTitle()}
{isPrivateGroup ? this.renderMemberCount() : null}
</div>

@ -1,37 +0,0 @@
import React from 'react';
interface Props {
//mouseButton: Number;
posX: number;
posY: number;
}
export class SessionDropdownTrigger extends React.Component<Props> {
public static defaultProps = {
//mouseButton: 2, // 0 is left click, 2 is right click
posX: 0,
posY: 0,
};
constructor(props: any) {
super(props);
}
public handleDropdownClick = (event: any) => {
event.preventDefault();
event.stopPropagation();
/*let x = event.clientX || (event.touches && event.touches[0].pageX);
let y = event.clientY || (event.touches && event.touches[0].pageY);
if (this.props.posX) {
x -= this.props.posX;
}
if (this.props.posY) {
y -= this.props.posY;
}*/
};
public render() {
return <div role="button" onClick={this.handleDropdownClick} />;
}
}

@ -84,14 +84,14 @@ export class SessionModal extends React.PureComponent<Props, State> {
});
window.removeEventListener('keyup', this.onKeyUp);
this.props.onClose();
if (this.props.onClose) {
this.props.onClose();
}
}
public onKeyUp(event: any) {
switch (event.key) {
case 'Enter':
this.props.onOk();
break;
case 'Esc':
case 'Escape':
this.close();

@ -0,0 +1,50 @@
import React from 'react';
import { QRCode } from 'react-qr-svg';
import { SessionModal } from './SessionModal';
import { SessionButton } from './SessionButton';
import { SessionHtmlRenderer } from './SessionHTMLRenderer';
interface Props {
value: string;
onClose: any;
}
export class SessionQRModal extends React.Component<Props> {
constructor(props: any) {
super(props);
}
public render() {
const { value, onClose } = this.props;
const theme = window.Events.getThemeSetting();
// Foreground equivalent to .session-modal background color
const bgColor = 'rgba(0, 0, 0, 0)';
const fgColor = theme === 'dark' ? '#FFFFFF' : '#1B1B1B';
return (
<SessionModal
title={window.i18n('QRCodeTitle')}
onOk={() => null}
onClose={onClose}
>
<div className="spacer-sm" />
<div className="qr-dialog__description text-subtle">
<SessionHtmlRenderer html={window.i18n('QRCodeDescription')} />
</div>
<div className="spacer-lg" />
<div id="qr">
<QRCode value={value} bgColor={bgColor} fgColor={fgColor} level="L" />
</div>
<div className="spacer-lg" />
<div className="session-modal__button-group">
<SessionButton text={window.i18n('close')} onClick={onClose} />
</div>
</SessionModal>
);
}
}

@ -0,0 +1,226 @@
import React from 'react';
import { SessionModal } from './SessionModal';
import { SessionButton } from './SessionButton';
interface Props {
onClose: any;
}
interface State {
error: string;
loadingPassword: boolean;
loadingSeed: boolean;
seed: string;
hasPassword: boolean | null;
passwordHash: string;
passwordValid: boolean;
}
export class SessionSeedModal extends React.Component<Props, State> {
constructor(props: any) {
super(props);
this.state = {
error: '',
loadingPassword: true,
loadingSeed: true,
seed: '',
hasPassword: null,
passwordHash: '',
passwordValid: false,
};
this.copySeed = this.copySeed.bind(this);
this.getSeed = this.getSeed.bind(this);
this.confirmPassword = this.confirmPassword.bind(this);
this.checkHasPassword = this.checkHasPassword.bind(this);
this.onEnter = this.onEnter.bind(this);
window.addEventListener('keyup', this.onEnter);
}
private renderPasswordView() {
const maxPasswordLen = 64;
const error = this.state.error;
const i18n = window.i18n;
const { onClose } = this.props;
return (
<>
<p>{i18n('showSeedPasswordRequest')}</p>
<input
type="password"
id="seed-input-password"
placeholder={i18n('password')}
maxLength={maxPasswordLen}
/>
{error && (
<>
<div className="spacer-xs" />
<div className="session-label danger">{error}</div>
</>
)}
<div className="spacer-lg" />
<div className="session-modal__button-group">
<SessionButton
text={i18n('confirm')}
onClick={this.confirmPassword}
/>
<SessionButton text={i18n('cancel')} onClick={onClose} />
</div>
</>
);
}
private renderSeedView() {
const i18n = window.i18n;
const { onClose } = this.props;
return (
<>
<div className="session-modal__centered text-center">
<p className="session-modal__description">
{i18n('seedSavePromptMain')}
<br />
<span className="text-subtle">{i18n('seedSavePromptAlt')}</span>
</p>
<div className="spacer-xs" />
<i className="session-modal__text-highlight">{this.state.seed}</i>
</div>
<div className="spacer-lg" />
<div className="session-modal__button-group">
<SessionButton text={i18n('ok')} onClick={onClose} />
<SessionButton
text={i18n('copySeed')}
onClick={() => {
this.copySeed(this.state.seed);
}}
/>
</div>
</>
);
}
public render() {
const i18n = window.i18n;
this.checkHasPassword();
this.getSeed().ignore();
const { onClose } = this.props;
const { hasPassword, passwordValid } = this.state;
const loading = this.state.loadingPassword || this.state.loadingSeed;
return (
<>
{!loading && (
<SessionModal
title={i18n('showSeed')}
onOk={() => null}
onClose={onClose}
>
<div className="spacer-sm" />
{hasPassword && !passwordValid ? (
<>{this.renderPasswordView()}</>
) : (
<>{this.renderSeedView()}</>
)}
</SessionModal>
)}
</>
);
}
private confirmPassword() {
const passwordHash = this.state.passwordHash;
const passwordValue = $('#seed-input-password').val();
const isPasswordValid = window.passwordUtil.matchesHash(
passwordValue,
passwordHash
);
if (!passwordValue) {
this.setState({
error: window.i18n('noGivenPassword'),
});
return false;
}
if (passwordHash && !isPasswordValid) {
this.setState({
error: window.i18n('invalidPassword'),
});
return false;
}
this.setState({
passwordValid: true,
error: '',
});
window.removeEventListener('keyup', this.onEnter);
return true;
}
private checkHasPassword() {
if (!this.state.loadingPassword) {
return;
}
const hashPromise = window.Signal.Data.getPasswordHash();
hashPromise.then((hash: any) => {
this.setState({
hasPassword: !!hash,
passwordHash: hash,
loadingPassword: false,
});
});
}
private async getSeed() {
if (this.state.seed) {
return false;
}
const manager = await window.getAccountManager();
const seed = manager.getCurrentMnemonic();
this.setState({
seed,
loadingSeed: false,
});
return true;
}
private copySeed(seed: string) {
window.clipboard.writeText(seed);
window.pushToast({
title: window.i18n('copiedMnemonic'),
type: 'success',
id: 'copySeedToast',
});
}
private onEnter(event: any) {
if (event.key === 'Enter') {
if ($('#seed-input-password').is(':focus')) {
this.confirmPassword();
}
}
}
}

@ -1,17 +0,0 @@
import React from 'react';
interface Props {
i18n: any;
}
export class SessionSettings extends React.Component<Props> {
constructor(props: any) {
super(props);
}
public render() {
//const i18n = this.props.i18n;
return <div />;
}
}

2
ts/global.d.ts vendored

@ -1,6 +1,8 @@
interface Window {
Events: any;
getAccountManager: any;
mnemonic: any;
clipboard: any;
passwordUtil: any;
dcodeIO: any;
libsignal: any;

@ -139,9 +139,9 @@
integrity sha512-Q1y515GcOdTHgagaVFhHnIFQ38ygs/kmxdNpvpou+raI9UO3YZcHDngBSYKQklcKlvA7iuQlmIKbzvmxcOE9CQ==
"@types/dompurify@^2.0.0":
version "2.0.1"
resolved "https://registry.yarnpkg.com/@types/dompurify/-/dompurify-2.0.1.tgz#0bf3a9f8ee21d81adb20b8c374ab034d6a74dbf7"
integrity sha512-OQ16dECrRv/I//woKkVUxyVGYR94W3qp3Wy//B63awHVe3h/1/URFqP5a/V2m4k01DEvWs1+z7FWW3xfM1lH3Q==
version "2.0.0"
resolved "https://registry.yarnpkg.com/@types/dompurify/-/dompurify-2.0.0.tgz#9616caa5bf2569aea2e4889d4f929d968c081b40"
integrity sha512-g/ilp+Bo6Ljy60i5LnjkGw00X7EIoFjoPGlxqZhV8TJ9fWEzXheioU1O+U/UzCzUA7pUDy/JNMytTQDJctpUHg==
dependencies:
"@types/trusted-types" "*"
@ -1243,19 +1243,6 @@ buble@^0.19.3:
os-homedir "^1.0.1"
vlq "^1.0.0"
buffer-alloc-unsafe@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0"
integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==
buffer-alloc@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec"
integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==
dependencies:
buffer-alloc-unsafe "^1.1.0"
buffer-fill "^1.0.0"
buffer-crc32@0.2.13, buffer-crc32@^0.2.1:
version "0.2.13"
resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242"
@ -1265,20 +1252,10 @@ buffer-equal@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-0.0.1.tgz#91bc74b11ea405bc916bc6aa908faafa5b4aac4b"
buffer-fill@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c"
integrity sha1-+PeLdniYiO858gXNY39o5wISKyw=
buffer-from@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.0.0.tgz#4cb8832d23612589b0406e9e2956c17f06fdf531"
buffer-from@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==
buffer-indexof@^1.0.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/buffer-indexof/-/buffer-indexof-1.1.1.tgz#52fabcc6a606d1a00302802648ef68f639da268c"
@ -1295,14 +1272,6 @@ buffer@^4.3.0:
ieee754 "^1.1.4"
isarray "^1.0.0"
buffer@^5.4.3:
version "5.4.3"
resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.4.3.tgz#3fbc9c69eb713d323e3fc1a895eee0710c072115"
integrity sha512-zvj65TkFeIt3i6aj5bIvJDzjjQQGs4o/sNoezg1F1kYap9Nu2jcUdpwzRSJTHMMzG0H7bZkn4rNQpImhuxWX2A==
dependencies:
base64-js "^1.0.2"
ieee754 "^1.1.4"
buffers@~0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/buffers/-/buffers-0.1.1.tgz#b24579c3bed4d6d396aeee6d9a8ae7f5482ab7bb"
@ -2553,11 +2522,6 @@ diffie-hellman@^5.0.0:
miller-rabin "^4.0.0"
randombytes "^2.0.0"
dijkstrajs@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/dijkstrajs/-/dijkstrajs-1.0.1.tgz#d3cd81221e3ea40742cfcde556d4e99e98ddc71b"
integrity sha1-082BIh4+pAdCz83lVtTpnpjdxxs=
dir-glob@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-2.0.0.tgz#0b205d2b6aef98238ca286598a8204d29d0a0034"
@ -5018,11 +4982,6 @@ isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
isarray@^2.0.1:
version "2.0.5"
resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723"
integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==
isbinaryfile@^4.0.2:
version "4.0.2"
resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-4.0.2.tgz#bfc45642da645681c610cca831022e30af426488"
@ -7022,11 +6981,6 @@ pngjs@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-3.0.1.tgz#b15086ac1ac47298c8fd3f9cdf364fa9879c4db6"
pngjs@^3.3.0:
version "3.4.0"
resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-3.4.0.tgz#99ca7d725965fb655814eaf65f38f12bbdbf555f"
integrity sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==
portfinder@^1.0.9:
version "1.0.13"
resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.13.tgz#bb32ecd87c27104ae6ee44b5a3ccbf0ebb1aede9"
@ -7520,18 +7474,10 @@ q@^1.1.2, q@~1.5.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/q/-/q-1.5.0.tgz#dd01bac9d06d30e6f219aecb8253ee9ebdc308f1"
qrcode@^1.4.4:
version "1.4.4"
resolved "https://registry.yarnpkg.com/qrcode/-/qrcode-1.4.4.tgz#f0c43568a7e7510a55efc3b88d9602f71963ea83"
integrity sha512-oLzEC5+NKFou9P0bMj5+v6Z40evexeE29Z9cummZXZ9QXyMr3lphkURzxjXgPJC5azpxcshoDWV1xE46z+/c3Q==
dependencies:
buffer "^5.4.3"
buffer-alloc "^1.2.0"
buffer-from "^1.1.1"
dijkstrajs "^1.0.1"
isarray "^2.0.1"
pngjs "^3.3.0"
yargs "^13.2.4"
qr.js@0.0.0:
version "0.0.0"
resolved "https://registry.yarnpkg.com/qr.js/-/qr.js-0.0.0.tgz#cace86386f59a0db8050fa90d9b6b0e88a1e364f"
integrity sha1-ys6GOG9ZoNuAUPqQ2baw6IoeNk8=
qs@5.2.0:
version "5.2.0"
@ -7758,10 +7704,13 @@ react-portal@^4.2.0:
dependencies:
prop-types "^15.5.8"
react-qrcode@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/react-qrcode/-/react-qrcode-0.2.0.tgz#a05cf2ae5ac57c3a9751e512132a821ed60533f9"
integrity sha512-3JzSzkTUUMb26sbq5/u75zw9l3gQ1BLvdCAYgRnAZ1wGJj1Su94pzv4g/XfzaJEj6h8Y0H9mYX4djmKBGZQHSQ==
react-qr-svg@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/react-qr-svg/-/react-qr-svg-2.2.1.tgz#f6f25820fdb2c39ad0d66a14a758e2f575717c68"
integrity sha512-rLDCZI9pIqD5lbBIatrqUMhP1gqQ7glqubXO/m/X87ikEPhXuY0hMLhYMuKoH4834G36ap8Az0HI4bXEJUN//w==
dependencies:
prop-types "^15.5.8"
qr.js "0.0.0"
react-redux@6.0.1:
version "6.0.1"
@ -10438,7 +10387,7 @@ yargs@^10.0.3:
y18n "^3.2.1"
yargs-parser "^8.0.0"
yargs@^13.2.4, yargs@^13.3.0:
yargs@^13.3.0:
version "13.3.0"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.0.tgz#4c657a55e07e5f2cf947f8a366567c04a0dedc83"
integrity sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==

Loading…
Cancel
Save