diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 522bc76f4..b07b94851 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -862,11 +862,17 @@ "devicePairingReceived": { "message": "Device Linking Received" }, + "devicePairingRequestReceivedLimitTitle": { + "message": "Device linking limit reached." + }, + "devicePairingRequestReceivedLimitDescription": { + "message": "To change your linked devices, please unlink a device first." + }, "devicePairingRequestReceivedNoListenerTitle": { "message": "Device linking request received." }, "devicePairingRequestReceivedNoListenerDescription": { - "message": "Device linking request received but you are not on the device linking screen. \nFirst go to Settings -> Device -> Link New Device." + "message": "Device linking request received but you are not on the device linking screen. \nGo to Settings > Device > Link New Device." }, "waitingForDeviceToRegister": { "message": "Waiting for device to register..." @@ -2373,11 +2379,23 @@ "verifyPassword": { "message": "Verify Password" }, - "devicePairingHeader": { - "message": "Open Session on your other device and navigate to the Linked Devices section in your user account screen. Select Link a Device to prepare your other device for pairing, then enter your Session ID below to link this device to your Session ID." + "devicePairingHeaderReassure": { + "message": "Linking may take up to one minute to register on your primary device. Please be patient." + }, + "devicePairingHeader_Step1": { + "message": "Open Session on your other device." + }, + "devicePairingHeader_Step2": { + "message": "Navigate to the Devices section in your user account screen." + }, + "devicePairingHeader_Step3": { + "message": "Select Link New Device to prepare your other device for pairing." + }, + "devicePairingHeader_Step4": { + "message": "Enter your Session ID below to link this device to your Session ID." }, "enterSessionIDHere": { - "message": "Enter other device’s Session ID here" + "message": "Enter your Session ID here" }, "continueYourSession": { "message": "Continue Your Session" diff --git a/js/background.js b/js/background.js index 89f5d242f..f342aeab9 100644 --- a/js/background.js +++ b/js/background.js @@ -1371,13 +1371,31 @@ }); Whisper.events.on('devicePairingRequestReceivedNoListener', async () => { + // If linking limit has been reached, let master know. + const ourKey = textsecure.storage.user.getNumber(); + const ourPubKey = window.libsession.Types.PubKey.cast(ourKey); + const authorisations = await window.libsession.Protocols.MultiDeviceProtocol.fetchPairingAuthorisations( + ourPubKey + ); + + const title = authorisations.length + ? window.i18n('devicePairingRequestReceivedLimitTitle') + : window.i18n('devicePairingRequestReceivedNoListenerTitle'); + + const description = authorisations.length + ? window.i18n( + 'devicePairingRequestReceivedLimitDescription', + window.CONSTANTS.MAX_LINKED_DEVICES + ) + : window.i18n('devicePairingRequestReceivedNoListenerDescription'); + + const type = authorisations.length ? 'info' : 'warning'; + window.pushToast({ - title: window.i18n('devicePairingRequestReceivedNoListenerTitle'), - description: window.i18n( - 'devicePairingRequestReceivedNoListenerDescription' - ), - type: 'info', - id: 'pairingRequestNoListener', + title, + description, + type, + id: 'pairingRequestReceived', shouldFade: false, }); }); diff --git a/preload.js b/preload.js index efafb66fa..c9f918a8e 100644 --- a/preload.js +++ b/preload.js @@ -82,6 +82,7 @@ window.CONSTANTS = new (function() { this.MAX_USERNAME_LENGTH = 20; this.MAX_GROUP_NAME_LENGTH = 64; this.DEFAULT_PUBLIC_CHAT_URL = appConfig.get('defaultPublicChatServer'); + this.MAX_LINKED_DEVICES = 1; this.MAX_CONNECTION_DURATION = 5000; this.MAX_MESSAGE_BODY_LENGTH = 64 * 1024; // Limited due to the proof-of-work requirement diff --git a/stylesheets/_session_signin.scss b/stylesheets/_session_signin.scss index 65f0eed86..03ccccc3f 100644 --- a/stylesheets/_session_signin.scss +++ b/stylesheets/_session_signin.scss @@ -75,6 +75,20 @@ &__content { width: 100%; padding-top: 20px; + + &__secret-words { + display: flex; + flex-direction: column; + align-items: center; + background-color: $session-shade-6; + padding: $session-margin-sm $session-margin-lg; + border-radius: 8px; + margin-bottom: 0px; + + label { + margin-bottom: 5px; + } + } } &__sections { @@ -228,11 +242,17 @@ &-description-long, &-signin-device-pairing-header { padding-top: 10px; - padding-bottom: 10px; + padding-bottom: 20px; color: $session-color-light-grey; text-align: center; font-size: 12px; line-height: 20px; + + ol { + margin-left: 20px; + padding: 0px; + text-align: justify; + } } &-id-editable { diff --git a/ts/components/session/RegistrationTabs.tsx b/ts/components/session/RegistrationTabs.tsx index db7fdd8da..be7d733ea 100644 --- a/ts/components/session/RegistrationTabs.tsx +++ b/ts/components/session/RegistrationTabs.tsx @@ -34,6 +34,7 @@ interface State { selectedTab: TabType; signInMode: SignInMode; signUpMode: SignUpMode; + secretWords: string | undefined; displayName: string; password: string; validatePassword: string; @@ -109,6 +110,7 @@ export class RegistrationTabs extends React.Component<{}, State> { selectedTab: TabType.Create, signInMode: SignInMode.Default, signUpMode: SignUpMode.Default, + secretWords: undefined, displayName: '', password: '', validatePassword: '', @@ -418,10 +420,41 @@ export class RegistrationTabs extends React.Component<{}, State> { return (
{window.i18n('devicePairingHeaderReassure')}
+ ) : ( +