You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			210 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			JavaScript
		
	
			
		
		
	
	
			210 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			JavaScript
		
	
| /* global
 | |
|   Whisper,
 | |
|   i18n,
 | |
|   libloki,
 | |
|   textsecure,
 | |
|   ConversationController,
 | |
|   $,
 | |
|   QRCode,
 | |
| */
 | |
| 
 | |
| // eslint-disable-next-line func-names
 | |
| (function() {
 | |
|   'use strict';
 | |
| 
 | |
|   window.Whisper = window.Whisper || {};
 | |
| 
 | |
|   Whisper.DevicePairingDialogView = Whisper.View.extend({
 | |
|     className: 'loki-dialog device-pairing-dialog modal',
 | |
|     templateName: 'device-pairing-dialog',
 | |
|     initialize() {
 | |
|       this.pubKeyRequests = [];
 | |
|       this.reset();
 | |
|       this.render();
 | |
|       this.showView();
 | |
|       this.qr = new QRCode(this.$('#qr')[0], {
 | |
|         correctLevel: QRCode.CorrectLevel.L,
 | |
|       });
 | |
|       this.qr.makeCode(textsecure.storage.user.getNumber());
 | |
|     },
 | |
|     reset() {
 | |
|       this.pubKey = null;
 | |
|       this.accepted = false;
 | |
|       this.isListening = false;
 | |
|       this.pubKeyToUnpair = null;
 | |
|       this.success = false;
 | |
|     },
 | |
|     events: {
 | |
|       'click #startPairing': 'startReceivingRequests',
 | |
|       'click #close': 'close',
 | |
|       'click .waitingForRequestView .cancel': 'stopReceivingRequests',
 | |
|       'click .requestReceivedView .skip': 'skipDevice',
 | |
|       'click #allowPairing': 'allowDevice',
 | |
|       'click .requestAcceptedView .ok': 'stopReceivingRequests',
 | |
|       'click .confirmUnpairView .cancel': 'stopReceivingRequests',
 | |
|       'click .confirmUnpairView .unpairDevice': 'confirmUnpairDevice',
 | |
|     },
 | |
|     render_attributes() {
 | |
|       return {
 | |
|         defaultTitle: i18n('pairedDevices'),
 | |
|         waitingForRequestTitle: i18n('waitingForDeviceToRegister'),
 | |
|         requestReceivedTitle: i18n('devicePairingReceived'),
 | |
|         requestAcceptedTitle: i18n('devicePairingAccepted'),
 | |
|         startPairingText: i18n('pairNewDevice'),
 | |
|         cancelText: i18n('cancel'),
 | |
|         unpairDevice: i18n('unpairDevice'),
 | |
|         closeText: i18n('close'),
 | |
|         skipText: i18n('skip'),
 | |
|         okText: i18n('ok'),
 | |
|         allowPairingText: i18n('allowPairing'),
 | |
|         confirmUnpairViewTitle: i18n('confirmUnpairingTitle'),
 | |
|       };
 | |
|     },
 | |
|     startReceivingRequests() {
 | |
|       this.trigger('startReceivingRequests');
 | |
|       this.isListening = true;
 | |
|       this.showView();
 | |
|     },
 | |
|     stopReceivingRequests() {
 | |
|       if (this.success) {
 | |
|         const deviceAlias = this.$('#deviceAlias')[0].value.trim();
 | |
|         const conv = ConversationController.get(this.pubKey);
 | |
|         if (conv) {
 | |
|           conv.setNickname(deviceAlias);
 | |
|         }
 | |
|       }
 | |
|       this.trigger('stopReceivingRequests');
 | |
|       this.reset();
 | |
|       this.showView();
 | |
|     },
 | |
|     requestReceived(secondaryDevicePubKey) {
 | |
|       // FIFO: push at the front of the array with unshift()
 | |
|       this.pubKeyRequests.unshift(secondaryDevicePubKey);
 | |
|       if (!this.pubKey) {
 | |
|         this.nextPubKey();
 | |
|         this.showView('requestReceived');
 | |
|       }
 | |
|     },
 | |
|     allowDevice() {
 | |
|       this.accepted = true;
 | |
|       this.trigger('devicePairingRequestAccepted', this.pubKey, errors =>
 | |
|         this.transmisssionCB(errors)
 | |
|       );
 | |
|       this.showView();
 | |
|     },
 | |
|     transmisssionCB(errors) {
 | |
|       if (!errors) {
 | |
|         this.$('.transmissionStatus').text(i18n('provideDeviceAlias'));
 | |
|         this.$('#deviceAliasView').show();
 | |
|         this.$('#deviceAlias').on('input', e => {
 | |
|           if (e.target.value.trim()) {
 | |
|             this.$('.requestAcceptedView .ok').removeAttr('disabled');
 | |
|           } else {
 | |
|             this.$('.requestAcceptedView .ok').attr('disabled', true);
 | |
|           }
 | |
|         });
 | |
|         this.$('.requestAcceptedView .ok').show();
 | |
|         this.$('.requestAcceptedView .ok').attr('disabled', true);
 | |
|         this.success = true;
 | |
|       } else {
 | |
|         this.$('.transmissionStatus').text(errors);
 | |
|         this.$('.requestAcceptedView .ok').show();
 | |
|       }
 | |
|     },
 | |
|     skipDevice() {
 | |
|       this.trigger('devicePairingRequestRejected', this.pubKey);
 | |
|       this.nextPubKey();
 | |
|       this.showView();
 | |
|     },
 | |
|     nextPubKey() {
 | |
|       // FIFO: pop at the back of the array using pop()
 | |
|       this.pubKey = this.pubKeyRequests.pop();
 | |
|     },
 | |
|     async confirmUnpairDevice() {
 | |
|       this.trigger('deviceUnpairingRequested', this.pubKeyToUnpair);
 | |
|       this.reset();
 | |
|       this.showView();
 | |
|     },
 | |
|     requestUnpairDevice(pubKey) {
 | |
|       this.pubKeyToUnpair = pubKey;
 | |
|       this.showView();
 | |
|     },
 | |
|     getPubkeyName(pubKey) {
 | |
|       const secretWords = window.mnemonic.pubkey_to_secret_words(pubKey);
 | |
|       const conv = ConversationController.get(pubKey);
 | |
|       const deviceAlias = conv ? conv.getNickname() : 'Unnamed Device';
 | |
|       return `${deviceAlias} (pairing secret: <i>${secretWords}</i>)`;
 | |
|     },
 | |
|     async showView() {
 | |
|       const defaultView = this.$('.defaultView');
 | |
|       const waitingForRequestView = this.$('.waitingForRequestView');
 | |
|       const requestReceivedView = this.$('.requestReceivedView');
 | |
|       const requestAcceptedView = this.$('.requestAcceptedView');
 | |
|       const confirmUnpairView = this.$('.confirmUnpairView');
 | |
|       if (this.pubKeyToUnpair) {
 | |
|         defaultView.hide();
 | |
|         requestReceivedView.hide();
 | |
|         waitingForRequestView.hide();
 | |
|         requestAcceptedView.hide();
 | |
|         confirmUnpairView.show();
 | |
|         const name = this.getPubkeyName(this.pubKeyToUnpair);
 | |
|         this.$('.confirmUnpairView #pubkey').html(name);
 | |
|       } else if (!this.isListening) {
 | |
|         requestReceivedView.hide();
 | |
|         waitingForRequestView.hide();
 | |
|         requestAcceptedView.hide();
 | |
|         confirmUnpairView.hide();
 | |
| 
 | |
|         const ourPubKey = textsecure.storage.user.getNumber();
 | |
|         defaultView.show();
 | |
|         const pubKeys = await libloki.storage.getSecondaryDevicesFor(ourPubKey);
 | |
|         this.$('#pairedPubKeys').empty();
 | |
|         if (pubKeys && pubKeys.length > 0) {
 | |
|           this.$('#startPairing').attr('disabled', true);
 | |
|           pubKeys.forEach(x => {
 | |
|             const name = this.getPubkeyName(x);
 | |
|             const li = $('<li>').html(name);
 | |
|             if (window.lokiFeatureFlags.multiDeviceUnpairing) {
 | |
|               const link = $('<a>')
 | |
|                 .text('Unpair')
 | |
|                 .attr('href', '#');
 | |
|               link.on('click', () => this.requestUnpairDevice(x));
 | |
|               li.append(' - ');
 | |
|               li.append(link);
 | |
|             }
 | |
|             this.$('#pairedPubKeys').append(li);
 | |
|           });
 | |
|         } else {
 | |
|           this.$('#startPairing').removeAttr('disabled');
 | |
|           this.$('#pairedPubKeys').append('<li>No paired devices</li>');
 | |
|         }
 | |
|       } else if (this.accepted) {
 | |
|         defaultView.hide();
 | |
|         requestReceivedView.hide();
 | |
|         waitingForRequestView.hide();
 | |
|         requestAcceptedView.show();
 | |
|       } else if (this.pubKey) {
 | |
|         const secretWords = window.mnemonic.pubkey_to_secret_words(this.pubKey);
 | |
|         this.$('.secretWords').text(secretWords);
 | |
|         requestReceivedView.show();
 | |
|         waitingForRequestView.hide();
 | |
|         requestAcceptedView.hide();
 | |
|         defaultView.hide();
 | |
|       } else {
 | |
|         waitingForRequestView.show();
 | |
|         requestReceivedView.hide();
 | |
|         requestAcceptedView.hide();
 | |
|         defaultView.hide();
 | |
|       }
 | |
|     },
 | |
|     close() {
 | |
|       this.remove();
 | |
|       this.qr.clear();
 | |
|       if (this.pubKey && !this.accepted) {
 | |
|         this.trigger('devicePairingRequestRejected', this.pubKey);
 | |
|       }
 | |
|       this.trigger('close');
 | |
|     },
 | |
|   });
 | |
| })();
 |