From 3a78f47cd7249c862a609a3d12c4a9280ff09f9a Mon Sep 17 00:00:00 2001 From: sachaaaaa Date: Fri, 30 Aug 2019 11:29:53 +1000 Subject: [PATCH 1/2] Secondary device registration: UX changes (show countdown, disable button, etc.) --- background.html | 3 +- js/views/standalone_registration_view.js | 74 +++++++++++++++++++----- stylesheets/_global.scss | 8 +++ 3 files changed, 70 insertions(+), 15 deletions(-) diff --git a/background.html b/background.html index a1f9c94c9..bc0ed8687 100644 --- a/background.html +++ b/background.html @@ -658,8 +658,9 @@
+
- Link + diff --git a/js/views/standalone_registration_view.js b/js/views/standalone_registration_view.js index ef64c4be7..cbf91f068 100644 --- a/js/views/standalone_registration_view.js +++ b/js/views/standalone_registration_view.js @@ -13,6 +13,8 @@ className: 'full-screen-flow standalone-fullscreen', initialize() { this.accountManager = getAccountManager(); + // Clean status in case the app closed unexpectedly + textsecure.storage.remove('secondaryDeviceStatus'); this.render(); @@ -50,12 +52,14 @@ this.registrationParams = {}; this.$pages = this.$('.page'); - this.pairingTimeout = null; + this.pairingInterval = null; this.showRegisterPage(); this.onValidatePassword(); - this.onSecondaryDeviceRegistered = this.onSecondaryDeviceRegistered.bind(this); + this.onSecondaryDeviceRegistered = this.onSecondaryDeviceRegistered.bind( + this + ); }, events: { 'validation input.number': 'onValidation', @@ -108,6 +112,9 @@ const input = this.trim(this.$passwordInput.val()); + // Ensure we clear the secondary device registration status + textsecure.storage.remove('secondaryDeviceStatus'); + try { await window.setPassword(input); await this.accountManager.registerSingleDevice( @@ -129,11 +136,19 @@ this.showProfilePage(mnemonic, language); }, onSecondaryDeviceRegistered() { + clearInterval(this.pairingInterval); // Ensure the left menu is updated Whisper.events.trigger('userChanged', { isSecondaryDevice: true }); this.$el.trigger('openInbox'); }, async registerSecondaryDevice() { + if (textsecure.storage.get('secondaryDeviceStatus') === 'ongoing') { + return; + } + textsecure.storage.put('secondaryDeviceStatus', 'ongoing'); + this.$('#register-secondary-device') + .attr('disabled', 'disabled') + .text('Sending...'); const mnemonic = this.$('#mnemonic-display').text(); const language = this.$('#mnemonic-display-language').val(); const primaryPubKey = this.$('#primary-pubkey').val(); @@ -147,26 +162,57 @@ 'secondaryDeviceRegistration', this.onSecondaryDeviceRegistered ); - clearTimeout(this.pairingTimeout); - this.pairingTimeout = setTimeout(() => { - this.$('.standalone-secondary-device #error').text( - 'The primary device has not responded within 1 minute. Ensure it is connected.' + clearInterval(this.pairingInterval); + let countDown = 60; + const onError = async error => { + clearInterval(this.pairingInterval); + this.$('.standalone-secondary-device #error') + .text(error) + .show(); + const sleep = ms => new Promise(resolve => setTimeout(resolve, ms)); + // If the registration started, ensure it's finished + while ( + textsecure.storage.protocol.getIdentityKeyPair() && + !Whisper.Registration.isDone() + ) { + // eslint-disable-next-line no-await-in-loop + await sleep(100); + } + Whisper.Registration.remove(); + Whisper.RotateSignedPreKeyListener.stop(); + textsecure.storage.remove('secondaryDeviceStatus'); + window.ConversationController.reset(); + this.$('#register-secondary-device') + .removeAttr('disabled') + .text('Link'); + }; + const countDownCallBack = () => { + if (countDown > 0) { + this.$('#register-secondary-device').text( + `Waiting for Primary Device... (${countDown})` + ); + countDown -= 1; + return; + } + onError( + 'The primary device has not responded within 1 minute. Ensure that you accept the pairing on the primary device.' ); - this.$('.standalone-secondary-device #error').show(); - }, 60000); - textsecure.storage.put('secondaryDeviceStatus', 'ongoing'); + }; try { await this.accountManager.registerSingleDevice( mnemonic, language, - 'John Smith' + null ); await this.accountManager.requestPairing(primaryPubKey); + countDownCallBack(); + this.pairingInterval = setInterval(countDownCallBack, 1000); + const pubkey = textsecure.storage.user.getNumber(); + this.$('.standalone-secondary-device #pubkey').text( + `Here is your pubkey:\n${pubkey}` + ); } catch (e) { - textsecure.storage.remove('secondaryDeviceStatus'); - this.$('.standalone-secondary-device #error').text(e); - this.$('.standalone-secondary-device #error').show(); - clearTimeout(this.pairingTimeout); + onError(e); } }, registerWithMnemonic() { diff --git a/stylesheets/_global.scss b/stylesheets/_global.scss index 973f420ea..e8cbafeb1 100644 --- a/stylesheets/_global.scss +++ b/stylesheets/_global.scss @@ -714,6 +714,14 @@ $loading-height: 16px; .button { background: $color-loki-green-gradient; border-radius: 100px; + + &[disabled='disabled'] { + &, + &:hover { + background: $color-loki-dark-gray; + cursor: default; + } + } } #mnemonic-display { From 7b262561a5b1f8c6163fcc57c04cf6561a98a958 Mon Sep 17 00:00:00 2001 From: sachaaaaa Date: Mon, 2 Sep 2019 10:19:09 +1000 Subject: [PATCH 2/2] simplify scss for disabled button --- stylesheets/_global.scss | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/stylesheets/_global.scss b/stylesheets/_global.scss index e8cbafeb1..cd3628cd0 100644 --- a/stylesheets/_global.scss +++ b/stylesheets/_global.scss @@ -715,12 +715,9 @@ $loading-height: 16px; background: $color-loki-green-gradient; border-radius: 100px; - &[disabled='disabled'] { - &, - &:hover { - background: $color-loki-dark-gray; - cursor: default; - } + &:disabled, &:disabled:hover { + background: $color-loki-dark-gray; + cursor: default; } }