From 8ee282b1aa6295ced7280c5f786a1898cd9272fd Mon Sep 17 00:00:00 2001 From: lilia Date: Fri, 6 Mar 2015 11:43:53 -0800 Subject: [PATCH] Restyle registration page When first intalling, users will no longer be presented with the option to register as a standalone client. For developer convenience, the standalone form can still be found at chrome-extension://.../register.html Closes #159 --- Gruntfile.js | 3 +- images/appstore.svg | 129 +++++++++++++++++++++++++++ images/playstore.png | Bin 0 -> 9614 bytes js/options.js | 188 +++++++-------------------------------- js/register.js | 122 +++++++++++++++++++++++++ options.html | 127 +++++++++++++------------- register.html | 79 ++++++++++++++++ stylesheets/options.css | 158 ++++++++++++++++---------------- stylesheets/options.scss | 164 ++++++++++++++++++++++++++++++++++ 9 files changed, 675 insertions(+), 295 deletions(-) create mode 100644 images/appstore.svg create mode 100644 images/playstore.png create mode 100644 js/register.js create mode 100644 register.html create mode 100644 stylesheets/options.scss diff --git a/Gruntfile.js b/Gruntfile.js index 5bfc8cc5..6cac4725 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -127,7 +127,8 @@ module.exports = function(grunt) { sass: { stylesheets: { files: { - 'stylesheets/manifest.css': 'stylesheets/manifest.scss' + 'stylesheets/manifest.css': 'stylesheets/manifest.scss', + 'stylesheets/options.css': 'stylesheets/options.scss' } } }, diff --git a/images/appstore.svg b/images/appstore.svg new file mode 100644 index 00000000..ac111e59 --- /dev/null +++ b/images/appstore.svg @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/images/playstore.png b/images/playstore.png new file mode 100644 index 0000000000000000000000000000000000000000..9a50affda395c98ed77c3dff9321d00bd6bf32e7 GIT binary patch literal 9614 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. */ - ;(function() { - function validateCode() { - var verificationCode = $('#code').val().replace(/\D/g, ''); - if (verificationCode.length == 6) { - return verificationCode; - } - } - - function displayError(error) { - $('#error').hide().text(error).addClass('in').fadeIn(); - } - + 'use strict'; $(function() { - var phoneView = new Whisper.PhoneInputView({el: $('#phone-number-input')}); - phoneView.render(); if (textsecure.registration.isDone()) { - $('#complete-number').text(textsecure.utils.unencodeNumber(textsecure.storage.getUnencrypted("number_id"))[0]);//TODO: no + $('#complete-number').text( + textsecure.utils.unencodeNumber( + textsecure.storage.getUnencrypted("number_id") + )[0] + );//TODO: no $('#setup-complete').show().addClass('in'); } else { - $('#choose-setup').show().addClass('in'); - - $('input.number').on('validation', function() { - if ($('#number-container').hasClass('valid')) { - $('#request-sms, #request-voice').removeAttr('disabled'); - } else { - $('#request-sms, #request-voice').prop('disabled', 'disabled'); - } - }); - - $('#code').on('change', function() { - if (!validateCode()) - $('#code').addClass('invalid'); - else - $('#code').removeClass('invalid'); - }); - - $('#request-voice').click(function() { - $('#error').hide(); - var number = phoneView.validateNumber(); - if (number) { - textsecure.api.requestVerificationVoice(number).catch(displayError); - $('#step2').addClass('in').fadeIn(); - } else { - $('#number-container').addClass('invalid'); - } - }); - - $('#request-sms').click(function() { - $('#error').hide(); - var number = phoneView.validateNumber(); - if (number) { - textsecure.api.requestVerificationSMS(number).catch(displayError); - $('#step2').addClass('in').fadeIn(); - } else { - $('#number-container').addClass('invalid'); - } - }); - - $('#new-account').click(function(){ - $('#choose-setup').fadeOut(function() { - $('#single-device').addClass('in').fadeIn(); - }); - - $('#single-device .back').click(function() { - $('#single-device').fadeOut(function() { - $('#choose-setup').addClass('in').fadeIn(); - $('input.number').removeClass('invalid'); - }); - }); - - $('#single-device form').submit(function(e) { - e.preventDefault(); - $('#error').hide(); - var number = phoneView.validateNumber(); - var verificationCode = validateCode(); - if (number && verificationCode) { - $('#verifyCode').prop('disabled', 'disabled'); - $('#verify *').hide(); - $('#verify').show().addClass('in'); - $('#verify2').show(); - - textsecure.registerSingleDevice(number, verificationCode, function(step) { + $('#init-setup').show().addClass('in'); + $('#status').text("Connecting..."); + axolotl.protocol.createIdentityKeyRecvSocket().then(function(cryptoInfo) { + var qrCode = new QRCode(document.getElementById('qr')); + var socket = textsecure.api.getTempWebsocket(); + new WebSocketResource(socket, function(request) { + if (request.path == "/v1/address" && request.verb == "PUT") { + var proto = textsecure.protobuf.ProvisioningUuid.decode(request.body); + var url = [ 'tsdevice:/', '?uuid=', proto.uuid, '&pub_key=', + encodeURIComponent(btoa(getString(cryptoInfo.pubKey))) ].join(''); + $('#status').text(''); + qrCode.makeCode(url); + request.respond(200, 'OK'); + } else if (request.path == "/v1/message" && request.verb == "PUT") { + $('#qr').hide(); + textsecure.registerSecondDevice(request.body, cryptoInfo, function(step) { switch(step) { case 1: - $('#verify3').show(); + $('#status').text('Registering new device...'); break; case 2: - $('#verify4').show(); + $('#status').text('Generating keys...'); break; case 3: - $('#complete-number').text(number); - $('#verify').hide(); - $('#init-setup').hide().removeClass('in'); - $('#setup-complete').show().addClass('in'); + $('#status').text('Uploading keys...'); + break; + case 4: + $('#status').text('All done!'); textsecure.registration.done(); + $('#init-setup').hide(); + $('#setup-complete').show().addClass('in'); } - }).catch(function(error) { - $('#verify *').hide(); - $('#verifyCode').removeAttr('disabled'); - if (error.humanError) - displayError(error.humanError); - else - displayError(error); //XXX }); - } - }); - }); - - $('#new-device').click(function(){ - $('#choose-setup').fadeOut(function() { - $('#multi-device').addClass('in').fadeIn(); - }); - - $('#multi-device .back').click(function() { - $('#multi-device').fadeOut(function() { - $('#choose-setup').addClass('in').fadeIn(); - $('input.number').removeClass('invalid'); - }); - }); - - $('#multi-device .status').text("Connecting..."); - $('#setup-qr').html(''); - axolotl.protocol.createIdentityKeyRecvSocket().then(function(cryptoInfo) { - var qrCode = new QRCode(document.getElementById('setup-qr')); - - var socket = textsecure.api.getTempWebsocket(); - new WebSocketResource(socket, function(request) { - if (request.path == "/v1/address" && request.verb == "PUT") { - var proto = textsecure.protobuf.ProvisioningUuid.decode(request.body); - qrCode.makeCode('tsdevice:/' + - '?uuid=' + proto.uuid + - '&pub_key=' + encodeURIComponent(btoa(getString(cryptoInfo.pubKey)))); - $('img').removeAttr('style'); - $('#multi-device .status').text("Use your phone to scan the QR code."); - request.respond(200, 'OK'); - } else if (request.path == "/v1/message" && request.verb == "PUT") { - $('#init-setup').hide(); - $('#verify1done').text(''); - $('#verify2done').text(''); - $('#verify3done').text(''); - $('#verify4done').text(''); - $('#verify5done').text(''); - $('#verify').show().addClass('in'); - - textsecure.registerSecondDevice(request.body, cryptoInfo, function(step) { - switch(step) { - case 1: - $('#verify1done').text('done'); - break; - case 2: - $('#verify2done').text('done'); - break; - case 3: - $('#verify3done').text('done'); - break; - case 4: - //XXX: User needs to verify number before we continue - $('#verify4done').text('done'); - //$('#complete-number').text(parsedNumber); - textsecure.registration.done(); - //case 5: //TODO: Do sync to get 5! - $('#verify').hide(); - $('#setup-complete').show().addClass('in'); - textsecure.registration.done(); - } - }); - } else - console.log(request.path); - }); + } else + console.log(request.path); }); }); } diff --git a/js/register.js b/js/register.js new file mode 100644 index 00000000..5ff9dd50 --- /dev/null +++ b/js/register.js @@ -0,0 +1,122 @@ +/* vim: ts=4:sw=4 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +;(function() { + 'use strict'; + + function log(s) { + console.log(s); + $('#status').text(s); + } + + function validateCode() { + var verificationCode = $('#code').val().replace(/\D/g, ''); + if (verificationCode.length == 6) { + return verificationCode; + } + } + + function displayError(error) { + $('#error').hide().text(error).addClass('in').fadeIn(); + } + + var phoneView = new Whisper.PhoneInputView({el: $('#phone-number-input')}); + phoneView.$el.find('input.number').intlTelInput(); + + var number = textsecure.storage.getUnencrypted('number_id'); + if (number) { + $('input.number').val(number.split('.')[0]); + } + + $('input.number').on('validation', function() { + if ($('#number-container').hasClass('valid')) { + $('#request-sms, #request-voice').removeAttr('disabled'); + } else { + $('#request-sms, #request-voice').prop('disabled', 'disabled'); + } + }); + + $('#code').on('change', function() { + if (!validateCode()) + $('#code').addClass('invalid'); + else + $('#code').removeClass('invalid'); + }); + + $('#request-voice').click(function() { + $('#error').hide(); + var number = phoneView.validateNumber(); + if (number) { + textsecure.api.requestVerificationVoice(number).catch(displayError); + $('#step2').addClass('in').fadeIn(); + } else { + $('#number-container').addClass('invalid'); + } + }); + + $('#request-sms').click(function() { + $('#error').hide(); + var number = phoneView.validateNumber(); + if (number) { + textsecure.api.requestVerificationSMS(number).catch(displayError); + $('#step2').addClass('in').fadeIn(); + } else { + $('#number-container').addClass('invalid'); + } + }); + + $('#form').submit(function(e) { + e.preventDefault(); + log('registering'); + var number = $('input.number').val(); + var verificationCode = $('#code').val(); + var signalingKey = textsecure.crypto.getRandomBytes(32 + 20); + + var password = btoa(getString(textsecure.crypto.getRandomBytes(16))); + password = password.substring(0, password.length - 2); + + var registrationId = new Uint16Array(textsecure.crypto.getRandomBytes(2))[0]; + registrationId = registrationId & 0x3fff; + + log('clearing data'); + localStorage.clear(); + + localStorage.setItem('first_install_ran', 1); + textsecure.storage.putUnencrypted('registrationId', registrationId); + textsecure.storage.putEncrypted('signaling_key', signalingKey); + textsecure.storage.putEncrypted('password', password); + textsecure.storage.putUnencrypted('number_id', number + '.1'); + textsecure.storage.putUnencrypted('regionCode', libphonenumber.util.getRegionCodeForNumber(number)); + + log('verifying code'); + return textsecure.api.confirmCode( + number, verificationCode, password, signalingKey, registrationId, true + ).then(function() { + log('generating keys'); + return axolotl.protocol.generateKeys().then(function(keys) { + log('uploading keys'); + return textsecure.api.registerKeys(keys).then(function() { + textsecure.registration.done(); + log('done'); + chrome.runtime.reload(); + }); + }); + }).catch(function(e) { + log(e); + }); + }); + +})(); diff --git a/options.html b/options.html index d394801d..e0ba36c7 100644 --- a/options.html +++ b/options.html @@ -19,79 +19,82 @@ - -
-

TextSecure

-
-
-
-

I'm new to TextSecure

-
-
-

I have TextSecure installed on my phone.

-
-
-
-
-

-
-
-

-
-
-
-
-
- -
-
-
-
-
-
-
-
-
-
-
- - -
-
-
- - -
-
+
+
+
+
+
+ +
+
+

Welcome to Signal for Chrome

+

Private messaging from your web browser.

+
+
+
+
+
+
+
+

Step 1

+

Download the Mobile App

+
+
+

Step 2

+

Pair Your Device

+
+
+
+
+

+ To get started, download the TextSecure app for your Android phone. + Once you've installed it, proceed to Step 2. +

+

+
+

+ Using a QR code scanning app on your phone, scan the QR code below, then + open the link to pair your device. +

+
+
+
+
+
+ + + +
+
+
+
+
+
-
-
-
-
-
Receiving identity key...
-
Verifying number and setup code...
-
Generating keys...
-
Registering...
-
Syncing with existing devices...
+
+
+
+
+
+
+ +
+
+

Signal for Chrome

+

Private messaging from your web browser.

+
-
-
+ +

You are registered on TextSecure with number

- diff --git a/register.html b/register.html new file mode 100644 index 00000000..8e65a2f2 --- /dev/null +++ b/register.html @@ -0,0 +1,79 @@ + + + + + + Re-register TextSecure + + + + + + +
+
+
+
+ +
+
+

Create your Signal Account

+

Private messaging from your web browser.

+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+ + +
+
+

+ + +
+
+
+
+
+ +
+ + + + + + + + + + + + + + + + diff --git a/stylesheets/options.css b/stylesheets/options.css index 44f1c165..cea87b85 100644 --- a/stylesheets/options.css +++ b/stylesheets/options.css @@ -13,51 +13,74 @@ * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ +@font-face { + font-family: 'Roboto-Light'; + src: url("/fonts/Roboto-Light.ttf") format("truetype"); } +@font-face { + font-family: 'Roboto'; + src: url("/fonts/Roboto-Regular.ttf") format("truetype"); } +@font-face { + font-family: 'Roboto'; + src: url("/fonts/Roboto-Italic.ttf") format("truetype"); + font-style: italic; } +@font-face { + font-family: 'Roboto'; + src: url("/fonts/Roboto-Bold.ttf") format("truetype"); + font-weight: bold; } +body { + font-family: Roboto, "Helvetica Neue", Arial, Helvetica, sans-serif; } -* { - font-family: Ubuntu, Segoe, 'Lucidia Grande', sans-serif; -} - -.paper { - background-color: #fafafa; - @include box-shadow(5px 0 5px -2px #ddd, -5px 0 5px -2px #ddd); -} +header { + background: #2a92e7; + color: white; + padding-bottom: 2em; + margin-bottom: 2em; } +.container { + min-width: 650px; } h1 { font-size: 30pt; font-weight: normal; - padding-bottom: 10px; -} + padding-bottom: 10px; } -h2 { - font-size: 12pt; - font-weight: normal; -} - -.left-column { - float: left; - width: 45%; -} - -.right-column { - float: right; - width: 50%; -} - -.hidden { - display: none; -} +.tagline { + font-style: italic; } #textsecure-icon { - width: 50px; - height: 50px; -} + float: left; + margin-top: 20px; + max-width: 100%; } -#setup-qr { - max-width: 256px; - margin-top: 1em; -} +#step1, #step2 { + color: #2a92e7; + font-weight: bold; + font-size: small; + text-transform: uppercase; } + +h3.step { + margin-top: 0; + font-weight: bold; } + +.cta { + text-align: center; + border: 2px solid #f3f3f3; + border-radius: 10px; + padding: 1em 0; + min-height: 293px; } + +.help { + border-top: 2px solid #f3f3f3; + padding: 1.5em 0.1em; } + +.install { + display: inline-block; + margin-top: 90px; } + +#qr { + display: inline-block; } + #qr canvas { + display: none; } #verifyCode, #code, @@ -65,35 +88,28 @@ h2 { box-sizing: border-box; width: 100%; display: block; - margin-bottom: 0.5em; -} + margin-bottom: 0.5em; } #request-voice, #request-sms { - box-sizing: border-box; -} + box-sizing: border-box; } + #request-sms { width: 57%; - float: right; -} + float: right; } + #request-voice { width: 40%; - float: left; -} - -.regionCode { - width: 100%; - margin-bottom: 1em; -} + float: left; } .number-container { position: relative; - margin-bottom: 0.5em; -} + margin-bottom: 0.5em; } + .number-container .intl-tel-input, .number-container .number { - width: 100%; -} + width: 100%; } + .number-container::after { visibility: hidden; content: ' '; @@ -107,47 +123,37 @@ h2 { top: 0; left: 100%; margin: 3px 8px; - text-align: center; -} + text-align: center; } + .number-container.valid::after { visibility: visible; content: '✓'; background-color: #0f9d58; - color: #ffffff; -} + color: #ffffff; } + .number-container.invalid::after { visibility: visible; content: '!'; background-color: #f44336; - color: #ffffff; -} + color: #ffffff; } #error { color: white; font-weight: bold; padding: 0.5em; - text-align: center; -} -#error { background-color: #f44336; } + text-align: center; } + +#error { + background-color: #f44336; } + #error:before { content: '\26a0'; - padding-right: 0.5em; -} + padding-right: 0.5em; } + .narrow { box-sizing: border-box; - margin: 0 auto 5px; width: 275px; - max-width: 100%; -} - -#single-device form { - margin: 2em 0; -} - -input.form-control, select.form-control { - border-radius: 0; -} + max-width: 100%; } ul.country-list { - min-width: 197px !important; -} + min-width: 197px !important; } diff --git a/stylesheets/options.scss b/stylesheets/options.scss new file mode 100644 index 00000000..20c775fe --- /dev/null +++ b/stylesheets/options.scss @@ -0,0 +1,164 @@ +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +@import 'variables'; + +body { + font-family: $roboto; +} + +header { + background: $blue; + color: white; + padding-bottom: 2em; + margin-bottom: 2em; +} + +.container { + min-width: 650px; +} + +h1 { + font-size: 30pt; + font-weight: normal; + padding-bottom: 10px; +} + +.tagline { + font-style: italic; +} + +#textsecure-icon { + float: left; + margin-top: 20px; + max-width: 100%; +} + +#step1, #step2 { + color: $blue; + font-weight: bold; + font-size: small; + text-transform: uppercase; +} + +h3.step { + margin-top: 0; + font-weight: bold; +} + +.cta { + text-align: center; + border: 2px solid $grey_l; + border-radius: 10px; + padding: 1em 0; + min-height: 293px; +} + +.help { + border-top: 2px solid $grey_l; + padding: 1.5em 0.1em; +} + +.install { + display: inline-block; + margin-top: 90px; +} + +#qr { + display: inline-block; + + canvas { + display: none; + } +} + +#verifyCode, +#code, +#number { + box-sizing: border-box; + width: 100%; + display: block; + margin-bottom: 0.5em; +} + +#request-voice, +#request-sms { + box-sizing: border-box; +} +#request-sms { + width: 57%; + float: right; +} +#request-voice { + width: 40%; + float: left; +} + +.number-container { + position: relative; + margin-bottom: 0.5em; +} +.number-container .intl-tel-input, +.number-container .number { + width: 100%; +} +.number-container::after { + visibility: hidden; + content: ' '; + display: inline-block; + border-radius: 1.5em; + width: 1.5em; + height: 1.5em; + line-height: 1.5em; + color: #ffffff; + position: absolute; + top: 0; + left: 100%; + margin: 3px 8px; + text-align: center; +} +.number-container.valid::after { + visibility: visible; + content: '✓'; + background-color: #0f9d58; + color: #ffffff; +} +.number-container.invalid::after { + visibility: visible; + content: '!'; + background-color: #f44336; + color: #ffffff; +} + +#error { + color: white; + font-weight: bold; + padding: 0.5em; + text-align: center; +} +#error { background-color: #f44336; } +#error:before { + content: '\26a0'; + padding-right: 0.5em; +} +.narrow { + box-sizing: border-box; + width: 275px; + max-width: 100%; +} + +ul.country-list { + min-width: 197px !important; +}