add back link device in settings in a dialog
This commit is contained in:
parent
29da7c2d53
commit
4d950f859b
|
@ -979,6 +979,9 @@
|
|||
"allowPairing": {
|
||||
"message": "Allow Pairing"
|
||||
},
|
||||
"allowPairingWithDevice": {
|
||||
"message": "Allow pairing with this device?"
|
||||
},
|
||||
"provideDeviceAlias": {
|
||||
"message": "Please provide an alias for this paired device"
|
||||
},
|
||||
|
@ -2601,7 +2604,7 @@
|
|||
"message": "Devices"
|
||||
},
|
||||
"devicesSettingsDescription": {
|
||||
"message": "Managed linked devices"
|
||||
"message": "Manage linked devices"
|
||||
},
|
||||
"mnemonicEmpty": {
|
||||
"message": "Seed is mandatory"
|
||||
|
@ -2645,5 +2648,20 @@
|
|||
},
|
||||
"description": {
|
||||
"message": "Description"
|
||||
},
|
||||
"filterReceivedRequests": {
|
||||
"message": "Filter received requests"
|
||||
},
|
||||
"secretWords": {
|
||||
"message": "Secret words:"
|
||||
},
|
||||
"pairingDevice": {
|
||||
"message": "Pairing Device"
|
||||
},
|
||||
"gotPairingRequest": {
|
||||
"message": "Got a pairing request"
|
||||
},
|
||||
"devicePairedSuccessfully": {
|
||||
"message": "Device paired successfully"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -216,28 +216,6 @@
|
|||
showDevicePairingDialog() {
|
||||
const dialog = new Whisper.DevicePairingDialogView();
|
||||
|
||||
dialog.on('startReceivingRequests', () => {
|
||||
Whisper.events.on('devicePairingRequestReceived', pubKey =>
|
||||
dialog.requestReceived(pubKey)
|
||||
);
|
||||
});
|
||||
|
||||
dialog.on('stopReceivingRequests', () => {
|
||||
Whisper.events.off('devicePairingRequestReceived');
|
||||
});
|
||||
|
||||
dialog.on('devicePairingRequestAccepted', (pubKey, cb) =>
|
||||
Whisper.events.trigger('devicePairingRequestAccepted', pubKey, cb)
|
||||
);
|
||||
dialog.on('devicePairingRequestRejected', pubKey =>
|
||||
Whisper.events.trigger('devicePairingRequestRejected', pubKey)
|
||||
);
|
||||
dialog.on('deviceUnpairingRequested', pubKey =>
|
||||
Whisper.events.trigger('deviceUnpairingRequested', pubKey)
|
||||
);
|
||||
dialog.once('close', () => {
|
||||
Whisper.events.off('devicePairingRequestReceived');
|
||||
});
|
||||
this.el.append(dialog.el);
|
||||
},
|
||||
showDevicePairingWordsDialog() {
|
||||
|
|
|
@ -576,14 +576,6 @@
|
|||
h4 {
|
||||
margin-top: 8px;
|
||||
margin-bottom: 16px;
|
||||
white-space: -moz-pre-wrap; /* Mozilla */
|
||||
white-space: -hp-pre-wrap; /* HP printers */
|
||||
white-space: -o-pre-wrap; /* Opera 7 */
|
||||
white-space: -pre-wrap; /* Opera 4-6 */
|
||||
white-space: pre-wrap; /* CSS 2.1 */
|
||||
white-space: pre-line; /* CSS 3 (and 2.1 as well, actually) */
|
||||
word-wrap: break-word; /* IE */
|
||||
word-break: break-all;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -677,17 +677,13 @@ label {
|
|||
justify-content: flex-end;
|
||||
|
||||
.session-button {
|
||||
margin-left: $session-margin-sm;
|
||||
margin: $session-margin-xs;
|
||||
}
|
||||
|
||||
&__center {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.session-button {
|
||||
margin: 0 $session-margin-xs;
|
||||
}
|
||||
}
|
||||
|
||||
&__text-highlight {
|
||||
|
@ -915,20 +911,23 @@ label {
|
|||
|
||||
&-header {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background-color: $session-shade-6;
|
||||
height: $main-view-header-height;
|
||||
line-height: $main-view-header-height;
|
||||
font-weight: bold;
|
||||
font-size: 18px;
|
||||
|
||||
&-title {
|
||||
line-height: $main-view-header-height;
|
||||
font-weight: bold;
|
||||
font-size: 18px;
|
||||
text-align: center;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.session-button,
|
||||
.session-icon-button {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
position: absolute;
|
||||
right: $session-margin-lg;
|
||||
align-items: center;
|
||||
height: $main-view-header-height;
|
||||
margin-right: $session-margin-lg;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -248,3 +248,7 @@
|
|||
color: $session-color-light-grey;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.registration-content-centered {
|
||||
text-align: center;
|
||||
}
|
||||
|
|
|
@ -1,30 +1,22 @@
|
|||
import React from 'react';
|
||||
import React, { ChangeEvent } from 'react';
|
||||
import { QRCode } from 'react-qr-svg';
|
||||
|
||||
import { SessionModal } from './session/SessionModal';
|
||||
import { SessionButton } from './session/SessionButton';
|
||||
import { SessionSpinner } from './session/SessionSpinner';
|
||||
|
||||
interface Props {
|
||||
i18n: any;
|
||||
onClose: any;
|
||||
pubKeyToUnpair: string | null;
|
||||
pubKey: string | null;
|
||||
}
|
||||
|
||||
interface State {
|
||||
currentPubKey: string | null;
|
||||
accepted: boolean;
|
||||
isListening: boolean;
|
||||
success: boolean;
|
||||
loading: boolean;
|
||||
view:
|
||||
| 'default'
|
||||
| 'waitingForRequest'
|
||||
| 'requestReceived'
|
||||
| 'requestAccepted'
|
||||
| 'confirmUnpair';
|
||||
pubKeyRequests: Array<any>;
|
||||
data: Array<any>;
|
||||
currentView: 'filterRequestView' | 'qrcodeView';
|
||||
errors: any;
|
||||
loading: boolean;
|
||||
deviceAlias: string | null;
|
||||
}
|
||||
|
||||
export class DevicePairingDialog extends React.Component<Props, State> {
|
||||
|
@ -33,156 +25,149 @@ export class DevicePairingDialog extends React.Component<Props, State> {
|
|||
|
||||
this.closeDialog = this.closeDialog.bind(this);
|
||||
this.onKeyUp = this.onKeyUp.bind(this);
|
||||
this.startReceivingRequests = this.startReceivingRequests.bind(this);
|
||||
this.stopReceivingRequests = this.stopReceivingRequests.bind(this);
|
||||
this.startReceivingRequests = this.startReceivingRequests.bind(this);
|
||||
this.getPubkeyName = this.getPubkeyName.bind(this);
|
||||
this.skipDevice = this.skipDevice.bind(this);
|
||||
this.allowDevice = this.allowDevice.bind(this);
|
||||
this.validateSecondaryDevice = this.validateSecondaryDevice.bind(this);
|
||||
this.handleUpdateDeviceAlias = this.handleUpdateDeviceAlias.bind(this);
|
||||
|
||||
this.state = {
|
||||
currentPubKey: this.props.pubKey,
|
||||
currentPubKey: null,
|
||||
accepted: false,
|
||||
isListening: false,
|
||||
success: false,
|
||||
loading: true,
|
||||
view: 'default',
|
||||
pubKeyRequests: [],
|
||||
data: [],
|
||||
pubKeyRequests: Array(),
|
||||
currentView: 'qrcodeView',
|
||||
loading: false,
|
||||
errors: undefined,
|
||||
deviceAlias: null,
|
||||
};
|
||||
}
|
||||
|
||||
public componentDidMount() {
|
||||
this.getSecondaryDevices();
|
||||
public componentWillMount() {
|
||||
this.startReceivingRequests();
|
||||
}
|
||||
|
||||
public render() {
|
||||
const { i18n } = this.props;
|
||||
public componentWillUnmount() {
|
||||
this.closeDialog();
|
||||
}
|
||||
|
||||
const waitingForRequest = this.state.view === 'waitingForRequest';
|
||||
const nothingPaired = this.state.data.length === 0;
|
||||
/*
|
||||
dialog.on('deviceUnpairingRequested', pubKey =>
|
||||
Whisper.events.trigger('deviceUnpairingRequested', pubKey)
|
||||
);*/
|
||||
|
||||
public renderFilterRequestsView() {
|
||||
const { currentPubKey, accepted, deviceAlias } = this.state;
|
||||
const secretWords = window.mnemonic.pubkey_to_secret_words(currentPubKey);
|
||||
const deviceAliasPlaceholder = this.getPubkeyName(currentPubKey);
|
||||
const deviceName = deviceAliasPlaceholder.deviceAlias;
|
||||
|
||||
if (accepted) {
|
||||
return (
|
||||
<SessionModal
|
||||
title={window.i18n('provideDeviceAlias')}
|
||||
onOk={() => null}
|
||||
onClose={this.closeDialog}
|
||||
>
|
||||
<div className="session-modal__centered">
|
||||
<input onChange={this.handleUpdateDeviceAlias}>{deviceName}</input>
|
||||
<div className="session-modal__button-group">
|
||||
<SessionButton
|
||||
text={window.i18n('ok')}
|
||||
onClick={this.validateSecondaryDevice}
|
||||
disabled={!deviceAlias}
|
||||
/>
|
||||
</div>
|
||||
<SessionSpinner loading={this.state.loading} />
|
||||
</div>
|
||||
</SessionModal>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<SessionModal
|
||||
title={window.i18n('allowPairingWithDevice')}
|
||||
onOk={() => null}
|
||||
onClose={this.closeDialog}
|
||||
>
|
||||
<div className="session-modal__centered">
|
||||
<label>{window.i18n('secretWords')}</label>
|
||||
<div className="text-subtle">{secretWords}</div>
|
||||
<div className="session-modal__button-group">
|
||||
<SessionButton
|
||||
text={window.i18n('skip')}
|
||||
onClick={this.skipDevice}
|
||||
/>
|
||||
<SessionButton
|
||||
text={window.i18n('allowPairing')}
|
||||
onClick={this.allowDevice}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</SessionModal>
|
||||
);
|
||||
}
|
||||
|
||||
public renderQrCodeView() {
|
||||
const theme = window.Events.getThemeSetting();
|
||||
const requestReceived = this.hasReceivedRequests();
|
||||
const title = window.i18n('pairingDevice');
|
||||
|
||||
// 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 (
|
||||
<>
|
||||
{!this.state.loading && (
|
||||
<SessionModal
|
||||
title={i18n('pairedDevices')}
|
||||
onOk={() => null}
|
||||
onClose={this.closeDialog}
|
||||
>
|
||||
{waitingForRequest ? (
|
||||
<div className="session-modal__centered">
|
||||
<h3>{i18n('waitingForDeviceToRegister')}</h3>
|
||||
<small className="text-subtle">
|
||||
{i18n('pairNewDevicePrompt')}
|
||||
</small>
|
||||
<div className="spacer-lg" />
|
||||
<SessionModal title={title} onOk={() => null} onClose={this.closeDialog}>
|
||||
<div className="session-modal__centered">
|
||||
<h4>{window.i18n('waitingForDeviceToRegister')}</h4>
|
||||
<small className="text-subtle">
|
||||
{window.i18n('pairNewDevicePrompt')}
|
||||
</small>
|
||||
<div className="spacer-lg" />
|
||||
|
||||
<div id="qr">
|
||||
<QRCode
|
||||
value={window.textsecure.storage.user.getNumber()}
|
||||
bgColor={bgColor}
|
||||
fgColor={fgColor}
|
||||
level="L"
|
||||
/>
|
||||
</div>
|
||||
<div id="qr">
|
||||
<QRCode
|
||||
value={window.textsecure.storage.user.getNumber()}
|
||||
bgColor={bgColor}
|
||||
fgColor={fgColor}
|
||||
level="L"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="spacer-lg" />
|
||||
<div className="session-modal__button-group__center">
|
||||
<SessionButton
|
||||
text={i18n('cancel')}
|
||||
onClick={this.stopReceivingRequests}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="spacer-lg" />
|
||||
<div className="session-modal__button-group__center">
|
||||
{!requestReceived ? (
|
||||
<SessionButton
|
||||
text={window.i18n('cancel')}
|
||||
onClick={this.closeDialog}
|
||||
/>
|
||||
) : (
|
||||
<>
|
||||
{nothingPaired ? (
|
||||
<div className="session-modal__centered">
|
||||
<div>{i18n('noPairedDevices')}</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="session-modal__centered">
|
||||
{'renderPairedDevices'}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="spacer-lg" />
|
||||
<div className="session-modal__button-group__center">
|
||||
<SessionButton
|
||||
text={i18n('pairNewDevice')}
|
||||
onClick={this.startReceivingRequests}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
<div className="session-modal__button-group">
|
||||
<SessionButton
|
||||
text={window.i18n('filterReceivedRequests')}
|
||||
onClick={this.stopReceivingRequests}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</SessionModal>
|
||||
)}
|
||||
</>
|
||||
</div>
|
||||
</div>
|
||||
</SessionModal>
|
||||
);
|
||||
}
|
||||
|
||||
private showView(
|
||||
view?:
|
||||
| 'default'
|
||||
| 'waitingForRequest'
|
||||
| 'requestReceived'
|
||||
| 'requestAccepted'
|
||||
| 'confirmUnpair'
|
||||
) {
|
||||
if (!view) {
|
||||
this.setState({
|
||||
view: 'default',
|
||||
});
|
||||
public render() {
|
||||
const { currentView } = this.state;
|
||||
const renderQrCodeView = currentView === 'qrcodeView';
|
||||
const renderFilterRequestView = currentView === 'filterRequestView';
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (view === 'waitingForRequest') {
|
||||
this.setState({
|
||||
view,
|
||||
isListening: true,
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
this.setState({ view });
|
||||
}
|
||||
|
||||
private getSecondaryDevices() {
|
||||
const secondaryDevices = window.libloki.storage
|
||||
.getSecondaryDevicesFor(this.state.currentPubKey)
|
||||
.then(() => {
|
||||
this.setState({
|
||||
data: secondaryDevices,
|
||||
loading: false,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private startReceivingRequests() {
|
||||
this.showView('waitingForRequest');
|
||||
return (
|
||||
<>
|
||||
{renderQrCodeView && this.renderQrCodeView()}
|
||||
{renderFilterRequestView && this.renderFilterRequestsView()}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
private getPubkeyName(pubKey: string | null) {
|
||||
|
@ -197,74 +182,104 @@ export class DevicePairingDialog extends React.Component<Props, State> {
|
|||
return { deviceAlias, secretWords };
|
||||
}
|
||||
|
||||
private stopReceivingRequests() {
|
||||
if (this.state.success) {
|
||||
const aliasKey = 'deviceAlias';
|
||||
const deviceAlias = this.getPubkeyName(this.state.currentPubKey)[
|
||||
aliasKey
|
||||
];
|
||||
|
||||
const conv = window.ConversationController.get(this.state.currentPubKey);
|
||||
if (conv) {
|
||||
conv.setNickname(deviceAlias);
|
||||
}
|
||||
}
|
||||
|
||||
this.showView();
|
||||
private reset() {
|
||||
this.setState({
|
||||
currentPubKey: null,
|
||||
accepted: false,
|
||||
pubKeyRequests: Array(),
|
||||
currentView: 'filterRequestView',
|
||||
deviceAlias: null,
|
||||
});
|
||||
}
|
||||
|
||||
// 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();
|
||||
private startReceivingRequests() {
|
||||
this.reset();
|
||||
window.Whisper.events.on(
|
||||
'devicePairingRequestReceived',
|
||||
(pubKey: string) => {
|
||||
this.requestReceived(pubKey);
|
||||
}
|
||||
);
|
||||
this.setState({ currentView: 'qrcodeView' });
|
||||
}
|
||||
|
||||
// this.showView('requestReceived');
|
||||
// }
|
||||
// }
|
||||
private stopReceivingRequests() {
|
||||
this.setState({ currentView: 'filterRequestView' });
|
||||
window.Whisper.events.off('devicePairingRequestReceived');
|
||||
}
|
||||
|
||||
// private allowDevice() {
|
||||
// this.setState({
|
||||
// accepted: true,
|
||||
// });
|
||||
// window.Whisper.trigger(
|
||||
// 'devicePairingRequestAccepted',
|
||||
// this.state.currentPubKey,
|
||||
// (errors: any) => {
|
||||
// this.transmisssionCB(errors);
|
||||
private requestReceived(secondaryDevicePubKey: string | EventHandlerNonNull) {
|
||||
// FIFO: push at the front of the array with unshift()
|
||||
this.state.pubKeyRequests.unshift(secondaryDevicePubKey);
|
||||
window.pushToast({
|
||||
title: window.i18n('gotPairingRequest'),
|
||||
description: `${window.shortenPubkey(
|
||||
secondaryDevicePubKey
|
||||
)} ${window.i18n(
|
||||
'showPairingWordsTitle'
|
||||
)}: ${window.mnemonic.pubkey_to_secret_words(secondaryDevicePubKey)}`,
|
||||
});
|
||||
if (!this.state.currentPubKey) {
|
||||
this.nextPubKey();
|
||||
}
|
||||
}
|
||||
|
||||
// return true;
|
||||
// }
|
||||
// );
|
||||
// this.showView();
|
||||
// }
|
||||
private allowDevice() {
|
||||
this.setState({
|
||||
accepted: true,
|
||||
});
|
||||
}
|
||||
|
||||
// private transmisssionCB(errors: any) {
|
||||
// if (!errors) {
|
||||
// this.setState({
|
||||
// success: true,
|
||||
// });
|
||||
// } else {
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
private transmissionCB(errors: any) {
|
||||
if (!errors) {
|
||||
this.setState({
|
||||
errors: null,
|
||||
});
|
||||
this.closeDialog();
|
||||
window.pushToast({
|
||||
title: window.i18n('devicePairedSuccessfully'),
|
||||
});
|
||||
const conv = window.ConversationController.get(this.state.currentPubKey);
|
||||
if (conv) {
|
||||
conv.setNickname(this.state.deviceAlias);
|
||||
}
|
||||
|
||||
// private skipDevice() {
|
||||
// window.Whisper.trigger(
|
||||
// 'devicePairingRequestRejected',
|
||||
// this.state.currentPubKey
|
||||
// );
|
||||
// this.nextPubKey();
|
||||
// this.showView();
|
||||
// }
|
||||
// FIXME display error somewhere
|
||||
// FIXME display list of linked device
|
||||
// FIXME do not show linked device in list of contacts
|
||||
|
||||
// private nextPubKey() {
|
||||
// // FIFO: pop at the back of the array using pop()
|
||||
// const pubKeyRequests = this.state.pubKeyRequests;
|
||||
// this.setState({
|
||||
// currentPubKey: pubKeyRequests.pop(),
|
||||
// });
|
||||
// }
|
||||
return;
|
||||
}
|
||||
/* this.$('.transmissionStatus').text(errors);
|
||||
this.$('.requestAcceptedView .ok').show();*/
|
||||
|
||||
this.setState({
|
||||
errors: errors,
|
||||
});
|
||||
}
|
||||
|
||||
private skipDevice() {
|
||||
window.Whisper.events.trigger(
|
||||
'devicePairingRequestRejected',
|
||||
this.state.currentPubKey
|
||||
);
|
||||
|
||||
const hasNext = this.state.pubKeyRequests.length > 0;
|
||||
this.nextPubKey();
|
||||
if (!hasNext) {
|
||||
this.startReceivingRequests();
|
||||
}
|
||||
this.setState({
|
||||
currentView: hasNext ? 'filterRequestView' : 'qrcodeView',
|
||||
});
|
||||
}
|
||||
|
||||
private nextPubKey() {
|
||||
// FIFO: pop at the back of the array using pop()
|
||||
this.setState({
|
||||
currentPubKey: this.state.pubKeyRequests.pop(),
|
||||
});
|
||||
}
|
||||
|
||||
private onKeyUp(event: any) {
|
||||
switch (event.key) {
|
||||
|
@ -276,9 +291,42 @@ export class DevicePairingDialog extends React.Component<Props, State> {
|
|||
}
|
||||
}
|
||||
|
||||
private validateSecondaryDevice() {
|
||||
this.setState({ loading: true });
|
||||
window.Whisper.events.trigger(
|
||||
'devicePairingRequestAccepted',
|
||||
this.state.currentPubKey,
|
||||
(errors: any) => {
|
||||
this.transmissionCB(errors);
|
||||
|
||||
return true;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private hasReceivedRequests() {
|
||||
return this.state.currentPubKey || this.state.pubKeyRequests.length > 0;
|
||||
}
|
||||
|
||||
private closeDialog() {
|
||||
window.removeEventListener('keyup', this.onKeyUp);
|
||||
this.stopReceivingRequests();
|
||||
window.Whisper.events.off('devicePairingRequestReceived');
|
||||
if (this.state.currentPubKey && !this.state.accepted) {
|
||||
window.Whisper.events.trigger(
|
||||
'devicePairingRequestRejected',
|
||||
this.state.currentPubKey
|
||||
);
|
||||
}
|
||||
this.props.onClose();
|
||||
}
|
||||
|
||||
private handleUpdateDeviceAlias(value: ChangeEvent<HTMLInputElement>) {
|
||||
const trimmed = value.target.value.trim();
|
||||
if (!!trimmed) {
|
||||
this.setState({ deviceAlias: trimmed });
|
||||
} else {
|
||||
this.setState({ deviceAlias: null });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,10 +14,12 @@ export const MainViewController = {
|
|||
},
|
||||
|
||||
renderSettingsView: (category: SessionSettingCategory) => {
|
||||
ReactDOM.render(
|
||||
<SettingsView category={category} />,
|
||||
document.getElementById('main-view')
|
||||
);
|
||||
if (document.getElementById('main-view')) {
|
||||
ReactDOM.render(
|
||||
<SettingsView category={category} />,
|
||||
document.getElementById('main-view')
|
||||
);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -274,11 +274,13 @@ export class LeftPaneChannelSection extends React.Component<Props, State> {
|
|||
|
||||
return (
|
||||
<div className="left-pane-contact-bottom-buttons">
|
||||
{showEditButton && <SessionButton
|
||||
text={edit}
|
||||
buttonType={SessionButtonType.SquareOutline}
|
||||
buttonColor={SessionButtonColor.White}
|
||||
/>}
|
||||
{showEditButton && (
|
||||
<SessionButton
|
||||
text={edit}
|
||||
buttonType={SessionButtonType.SquareOutline}
|
||||
buttonColor={SessionButtonColor.White}
|
||||
/>
|
||||
)}
|
||||
<SessionButton
|
||||
text={addChannel}
|
||||
buttonType={SessionButtonType.SquareOutline}
|
||||
|
|
|
@ -280,11 +280,13 @@ export class LeftPaneContactSection extends React.Component<Props, State> {
|
|||
|
||||
return (
|
||||
<div className="left-pane-contact-bottom-buttons">
|
||||
{showEditButton && <SessionButton
|
||||
text={edit}
|
||||
buttonType={SessionButtonType.SquareOutline}
|
||||
buttonColor={SessionButtonColor.White}
|
||||
/>}
|
||||
{showEditButton && (
|
||||
<SessionButton
|
||||
text={edit}
|
||||
buttonType={SessionButtonType.SquareOutline}
|
||||
buttonColor={SessionButtonColor.White}
|
||||
/>
|
||||
)}
|
||||
{selectedTab === 0 ? (
|
||||
<SessionButton
|
||||
text={addContact}
|
||||
|
|
|
@ -132,7 +132,7 @@ export class LeftPaneSettingSection extends React.Component<any, State> {
|
|||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -208,6 +208,11 @@ export class LeftPaneSettingSection extends React.Component<any, State> {
|
|||
description: window.i18n('notificationSettingsDescription'),
|
||||
hidden: false,
|
||||
},
|
||||
{
|
||||
id: SessionSettingCategory.Devices,
|
||||
title: window.i18n('devicesSettingsTitle'),
|
||||
description: window.i18n('devicesSettingsDescription'),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ import {
|
|||
import { trigger } from '../../shims/events';
|
||||
import { SessionHtmlRenderer } from './SessionHTMLRenderer';
|
||||
import { SessionIdEditable } from './SessionIdEditable';
|
||||
import { SessionSpinner } from './SessionSpinner';
|
||||
|
||||
enum SignInMode {
|
||||
Default,
|
||||
|
@ -42,6 +43,7 @@ interface State {
|
|||
primaryDevicePubKey: string;
|
||||
mnemonicError: string | undefined;
|
||||
displayNameError: string | undefined;
|
||||
loading: boolean;
|
||||
}
|
||||
|
||||
const Tab = ({
|
||||
|
@ -115,6 +117,7 @@ export class RegistrationTabs extends React.Component<{}, State> {
|
|||
primaryDevicePubKey: '',
|
||||
mnemonicError: undefined,
|
||||
displayNameError: undefined,
|
||||
loading: false,
|
||||
};
|
||||
|
||||
this.accountManager = window.getAccountManager();
|
||||
|
@ -413,11 +416,12 @@ export class RegistrationTabs extends React.Component<{}, State> {
|
|||
}
|
||||
if (signInMode === SignInMode.LinkingDevice) {
|
||||
return (
|
||||
<div className="">
|
||||
<div className="registration-content-centered">
|
||||
<div className="session-signin-device-pairing-header">
|
||||
{window.i18n('devicePairingHeader')}
|
||||
</div>
|
||||
{this.renderEnterSessionID(true)}
|
||||
<SessionSpinner loading={this.state.loading} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -734,7 +738,7 @@ export class RegistrationTabs extends React.Component<{}, State> {
|
|||
if (passwordErrorString || passwordFieldsMatch) {
|
||||
window.pushToast({
|
||||
title: window.i18n('invalidPassword'),
|
||||
type: 'success',
|
||||
type: 'error',
|
||||
id: 'invalidPassword',
|
||||
});
|
||||
|
||||
|
@ -782,6 +786,9 @@ export class RegistrationTabs extends React.Component<{}, State> {
|
|||
if (window.textsecure.storage.get('secondaryDeviceStatus') === 'ongoing') {
|
||||
return;
|
||||
}
|
||||
this.setState({
|
||||
loading: true,
|
||||
});
|
||||
await this.resetRegistration();
|
||||
window.textsecure.storage.put('secondaryDeviceStatus', 'ongoing');
|
||||
|
||||
|
@ -798,7 +805,7 @@ export class RegistrationTabs extends React.Component<{}, State> {
|
|||
);
|
||||
|
||||
const onError = async (error: any) => {
|
||||
window.log.error.error(error);
|
||||
window.log.error(error);
|
||||
|
||||
await this.resetRegistration();
|
||||
};
|
||||
|
@ -826,16 +833,26 @@ export class RegistrationTabs extends React.Component<{}, State> {
|
|||
await this.accountManager.requestPairing(primaryPubKey);
|
||||
const pubkey = window.textsecure.storage.user.getNumber();
|
||||
const words = window.mnemonic.pubkey_to_secret_words(pubkey);
|
||||
window.console.log('pubkey_to_secret_words');
|
||||
window.console.log(`Here is your secret:\n${words}`);
|
||||
window.pushToast({
|
||||
title: `Here is your secret: "${words}"`,
|
||||
id: 'yourSecret',
|
||||
shouldFade: false,
|
||||
});
|
||||
} catch (e) {
|
||||
window.console.log(e);
|
||||
//onError(e);
|
||||
this.setState({
|
||||
loading: false,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private async onSecondaryDeviceRegistered() {
|
||||
// Ensure the left menu is updated
|
||||
this.setState({
|
||||
loading: false,
|
||||
});
|
||||
trigger('userChanged', { isSecondaryDevice: true });
|
||||
// will re-run the background initialisation
|
||||
trigger('registration_done');
|
||||
|
|
|
@ -6,6 +6,7 @@ import { SessionIconButton, SessionIconSize, SessionIconType } from './icon';
|
|||
|
||||
export const SessionRegistrationView: React.FC = () => (
|
||||
<div className="session-content">
|
||||
<div id="session-toast-container" />
|
||||
<div id="error" className="collapse" />
|
||||
<div className="session-content-close-button">
|
||||
<SessionIconButton
|
||||
|
|
|
@ -45,7 +45,14 @@ export class SettingsView extends React.Component<SettingsViewProps, State> {
|
|||
}
|
||||
|
||||
/* tslint:disable-next-line:max-func-body-length */
|
||||
public renderSettingInCategory() {
|
||||
public renderSettingInCategory(): JSX.Element {
|
||||
const { category } = this.props;
|
||||
if (category === SessionSettingCategory.Devices) {
|
||||
// special case for linked devices
|
||||
|
||||
return this.renderLinkedDevicesCategory();
|
||||
}
|
||||
|
||||
const { Settings } = window.Signal.Types;
|
||||
|
||||
// Grab initial values from database on startup
|
||||
|
@ -230,6 +237,7 @@ export class SettingsView extends React.Component<SettingsViewProps, State> {
|
|||
this.updateSetting(setting);
|
||||
});
|
||||
|
||||
|
||||
return (
|
||||
<div key={setting.id}>
|
||||
{shouldRenderSettings &&
|
||||
|
@ -307,4 +315,9 @@ export class SettingsView extends React.Component<SettingsViewProps, State> {
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private renderLinkedDevicesCategory(): JSX.Element {
|
||||
return <div />;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,35 +1,51 @@
|
|||
import React from 'react';
|
||||
import { SessionIconButton, SessionIconSize, SessionIconType } from '../icon';
|
||||
|
||||
import { SettingsViewProps } from './SessionSettings';
|
||||
import { SessionSettingCategory, SettingsViewProps } from './SessionSettings';
|
||||
import { SessionButton } from '../SessionButton';
|
||||
|
||||
export class SettingsHeader extends React.Component<SettingsViewProps> {
|
||||
public constructor(props: any) {
|
||||
super(props);
|
||||
this.showAddLinkedDeviceModal = this.showAddLinkedDeviceModal.bind(this);
|
||||
}
|
||||
|
||||
public focusSearch() {
|
||||
$('.left-pane-setting-section .session-search-input input').focus();
|
||||
}
|
||||
|
||||
public showAddLinkedDeviceModal() {
|
||||
window.Whisper.events.trigger('showDevicePairingDialog');
|
||||
}
|
||||
|
||||
public render() {
|
||||
const category = String(this.props.category);
|
||||
const categoryTitlePrefix = category[0].toUpperCase() + category.substr(1);
|
||||
const { category } = this.props;
|
||||
const categoryString = String(category);
|
||||
const categoryTitlePrefix =
|
||||
categoryString[0].toUpperCase() + categoryString.substr(1);
|
||||
// Remove 's' on the end to keep words in singular form
|
||||
const categoryTitle =
|
||||
categoryTitlePrefix[categoryTitlePrefix.length - 1] === 's'
|
||||
? `${categoryTitlePrefix.slice(0, -1)} Settings`
|
||||
: `${categoryTitlePrefix} Settings`;
|
||||
const showSearch = false;
|
||||
const showAddDevice = category === SessionSettingCategory.Devices;
|
||||
|
||||
return (
|
||||
<div className="session-settings-header">
|
||||
{categoryTitle}
|
||||
<div className="session-settings-header-title">{categoryTitle}</div>
|
||||
{showSearch && <SessionIconButton
|
||||
iconType={SessionIconType.Search}
|
||||
iconSize={SessionIconSize.Huge}
|
||||
onClick={this.focusSearch}
|
||||
/>}
|
||||
/>
|
||||
}
|
||||
{showAddDevice && (
|
||||
<SessionButton
|
||||
text={window.i18n('linkNewDevice')}
|
||||
onClick={this.showAddLinkedDeviceModal}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue