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.
		
		
		
		
		
			
		
			
				
	
	
		
			195 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			JavaScript
		
	
			
		
		
	
	
			195 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			JavaScript
		
	
| /*
 | |
|  * vim: ts=4:sw=4:expandtab
 | |
|  */
 | |
| (function () {
 | |
|   'use strict';
 | |
|   window.Whisper = window.Whisper || {};
 | |
| 
 | |
|   var State = {
 | |
|     IMPORTING: 1,
 | |
|     COMPLETE: 2,
 | |
|     LIGHT_COMPLETE: 3,
 | |
|   };
 | |
| 
 | |
|   var IMPORT_STARTED = 'importStarted';
 | |
|   var IMPORT_COMPLETE = 'importComplete';
 | |
|   var IMPORT_LOCATION = 'importLocation';
 | |
| 
 | |
|   Whisper.Import = {
 | |
|     isStarted: function() {
 | |
|       return Boolean(storage.get(IMPORT_STARTED));
 | |
|     },
 | |
|     isComplete: function() {
 | |
|       return Boolean(storage.get(IMPORT_COMPLETE));
 | |
|     },
 | |
|     isIncomplete: function() {
 | |
|       return this.isStarted() && !this.isComplete();
 | |
|     },
 | |
|     start: function() {
 | |
|       return storage.put(IMPORT_STARTED, true);
 | |
|     },
 | |
|     complete: function() {
 | |
|       return storage.put(IMPORT_COMPLETE, true);
 | |
|     },
 | |
|     saveLocation: function(location) {
 | |
|       return storage.put(IMPORT_LOCATION, location);
 | |
|     },
 | |
|     reset: function() {
 | |
|       return Whisper.Database.clear();
 | |
|     }
 | |
|   };
 | |
| 
 | |
|   Whisper.ImportView = Whisper.View.extend({
 | |
|     templateName: 'import-flow-template',
 | |
|     className: 'full-screen-flow',
 | |
|     events: {
 | |
|       'click .choose': 'onImport',
 | |
|       'click .restart': 'onRestart',
 | |
|       'click .cancel': 'onCancel',
 | |
|       'click .register': 'onRegister',
 | |
|     },
 | |
|     initialize: function() {
 | |
|       if (Whisper.Import.isIncomplete()) {
 | |
|         this.error = true;
 | |
|       }
 | |
| 
 | |
|       this.render();
 | |
|       this.pending = Promise.resolve();
 | |
|     },
 | |
|     render_attributes: function() {
 | |
|       if (this.error) {
 | |
|         return {
 | |
|           isError: true,
 | |
|           errorHeader: i18n('importErrorHeader'),
 | |
|           errorMessage: i18n('importError'),
 | |
|           chooseButton: i18n('importAgain'),
 | |
|         };
 | |
|       }
 | |
| 
 | |
|       var restartButton = i18n('importCompleteStartButton');
 | |
|       var registerButton = i18n('importCompleteLinkButton');
 | |
|       var step = 'step2';
 | |
| 
 | |
|       if (this.state === State.IMPORTING) {
 | |
|         step = 'step3';
 | |
|       } else if (this.state === State.COMPLETE) {
 | |
|         registerButton = null;
 | |
|         step = 'step4';
 | |
|       } else if (this.state === State.LIGHT_COMPLETE) {
 | |
|         restartButton = null;
 | |
|         step = 'step4';
 | |
|       }
 | |
| 
 | |
|       return {
 | |
|         isStep2: step === 'step2',
 | |
|         chooseHeader: i18n('loadDataHeader'),
 | |
|         choose: i18n('loadDataDescription'),
 | |
|         chooseButton: i18n('chooseDirectory'),
 | |
| 
 | |
|         isStep3: step === 'step3',
 | |
|         importingHeader: i18n('importingHeader'),
 | |
| 
 | |
|         isStep4: step === 'step4',
 | |
|         completeHeader: i18n('importCompleteHeader'),
 | |
|         restartButton: restartButton,
 | |
|         registerButton: registerButton,
 | |
|       };
 | |
|     },
 | |
|     onRestart: function() {
 | |
|       return window.restart();
 | |
|     },
 | |
|     onCancel: function() {
 | |
|       this.trigger('cancel');
 | |
|     },
 | |
|     onImport: function() {
 | |
|       window.Signal.Backup.getDirectoryForImport().then(function(directory) {
 | |
|         this.doImport(directory);
 | |
|       }.bind(this), function(error) {
 | |
|         if (error.name !== 'ChooseError') {
 | |
|           console.log(
 | |
|             'Error choosing directory:',
 | |
|             error && error.stack ? error.stack : error
 | |
|           );
 | |
|         }
 | |
|       });
 | |
|     },
 | |
|     onRegister: function() {
 | |
|       // AppView listens for this, and opens up InstallView to the QR code step to
 | |
|       //   finish setting this device up.
 | |
|       this.trigger('light-import');
 | |
|     },
 | |
| 
 | |
|     doImport: function(directory) {
 | |
|       window.removeSetupMenuItems();
 | |
| 
 | |
|       this.error = null;
 | |
|       this.state = State.IMPORTING;
 | |
|       this.render();
 | |
| 
 | |
|       // Wait for prior database interaction to complete
 | |
|       this.pending = this.pending.then(function() {
 | |
|         // For resilience to interruption, clear database both before and on failure
 | |
|         return Whisper.Import.reset();
 | |
|       }).then(function() {
 | |
|         return Promise.all([
 | |
|           Whisper.Import.start(),
 | |
|           window.Signal.Backup.importFromDirectory(directory)
 | |
|         ]);
 | |
|       }).then(function(results) {
 | |
|         var importResult = results[1];
 | |
| 
 | |
|         // A full import changes so much we need a restart of the app
 | |
|         if (importResult.fullImport) {
 | |
|           return this.finishFullImport(directory);
 | |
|         }
 | |
| 
 | |
|         // A light import just brings in contacts, groups, and messages. And we need a
 | |
|         //   normal link to finish the process.
 | |
|         return this.finishLightImport(directory);
 | |
|       }.bind(this)).catch(function(error) {
 | |
|         console.log('Error importing:', error && error.stack ? error.stack : error);
 | |
| 
 | |
|         this.error = error || new Error('Something went wrong!');
 | |
|         this.state = null;
 | |
|         this.render();
 | |
| 
 | |
|         return Whisper.Import.reset();
 | |
|       }.bind(this));
 | |
|     },
 | |
|     finishLightImport: function(directory) {
 | |
|       ConversationController.reset();
 | |
| 
 | |
|       return ConversationController.load().then(function() {
 | |
|         return Promise.all([
 | |
|             Whisper.Import.saveLocation(directory),
 | |
|             Whisper.Import.complete(),
 | |
|           ]);
 | |
|       }).then(function() {
 | |
|         this.state = State.LIGHT_COMPLETE;
 | |
|         this.render();
 | |
|       }.bind(this));
 | |
|     },
 | |
|     finishFullImport: function(directory) {
 | |
|       // Catching in-memory cache up with what's in indexeddb now...
 | |
|       // NOTE: this fires storage.onready, listened to across the app. We'll restart
 | |
|       //   to complete the install to start up cleanly with everything now in the DB.
 | |
|       return storage.fetch()
 | |
|         .then(function() {
 | |
|           return Promise.all([
 | |
|             // Clearing any migration-related state inherited from the Chrome App
 | |
|             storage.remove('migrationState'),
 | |
|             storage.remove('migrationEnabled'),
 | |
|             storage.remove('migrationEverCompleted'),
 | |
|             storage.remove('migrationStorageLocation'),
 | |
| 
 | |
|             Whisper.Import.saveLocation(directory),
 | |
|             Whisper.Import.complete()
 | |
|           ]);
 | |
|         }).then(function() {
 | |
|           this.state = State.COMPLETE;
 | |
|           this.render();
 | |
|         }.bind(this));
 | |
|     }
 | |
|   });
 | |
| })();
 |