From 793001e133b991cab28e8c611c1c54eb4cce406e Mon Sep 17 00:00:00 2001 From: Juan Cruz Viotti Date: Thu, 10 Mar 2016 11:46:41 -0400 Subject: [PATCH] Move burn state to ImageWriterService Previously, the burn state lived in the controller, however if the user moved to another page (the settings page for example) and then returned, the progress state would be lost, leading to a broken progress bar. Fixes: https://github.com/resin-io/etcher/issues/190 --- lib/browser/app.js | 25 +++++++------- lib/browser/modules/image-writer.js | 39 ++++++++++++++++++---- lib/partials/main.html | 14 ++++---- tests/browser/modules/image-writer.spec.js | 29 ++++++++++++++++ 4 files changed, 81 insertions(+), 26 deletions(-) diff --git a/lib/browser/app.js b/lib/browser/app.js index 6e9cef30..216146a3 100644 --- a/lib/browser/app.js +++ b/lib/browser/app.js @@ -35,6 +35,7 @@ require('./browser/modules/settings'); require('./browser/modules/drive-scanner'); require('./browser/modules/image-writer'); require('./browser/modules/path'); +require('./browser/modules/notifier'); require('./browser/modules/analytics'); const app = angular.module('Etcher', [ @@ -47,6 +48,7 @@ const app = angular.module('Etcher', [ 'Etcher.settings', 'Etcher.drive-scanner', 'Etcher.image-writer', + 'Etcher.notifier', 'Etcher.analytics' ]); @@ -74,6 +76,8 @@ app.config(function($stateProvider, $urlRouterProvider) { app.controller('AppController', function( $q, $state, + $scope, + NotifierService, DriveScannerService, SelectionStateService, ImageWriterService, @@ -87,12 +91,16 @@ app.controller('AppController', function( AnalyticsService.logEvent('Restart'); if (!this.writer.isBurning()) { - this.state = { - progress: 0, - percentage: 0 - }; + this.writer.resetState(); } + NotifierService.subscribe($scope, 'image-writer:state', function(state) { + AnalyticsService.log(`Progress: ${state.progress}% at ${state.speed} MB/s`); + + // Show progress inline in operating system task bar + currentWindow.setProgressBar(state.progress / 100); + }); + this.scanner.start(2000).on('scan', function(drives) { // Notice we only autoselect the drive if there is an image, @@ -183,14 +191,7 @@ app.controller('AppController', function( device: drive.device }); - return self.writer.burn(image, drive, function(state) { - self.state = state; - AnalyticsService.log(`Progress: ${self.state.progress}% at ${self.state.speed} MB/s`); - - // Show progress inline in operating system task bar - currentWindow.setProgressBar(self.state.progress / 100); - - }).then(function() { + return self.writer.burn(image, drive).then(function() { AnalyticsService.logEvent('Done'); $state.go('success'); }).catch(dialog.showError).finally(function() { diff --git a/lib/browser/modules/image-writer.js b/lib/browser/modules/image-writer.js index c87aaec9..84c64cbc 100644 --- a/lib/browser/modules/image-writer.js +++ b/lib/browser/modules/image-writer.js @@ -30,14 +30,39 @@ if (window.mocha) { } require('./settings'); +require('./notifier'); const imageWriter = angular.module('Etcher.image-writer', [ - 'Etcher.settings' + 'Etcher.settings', + 'Etcher.notifier' ]); -imageWriter.service('ImageWriterService', function($q, $timeout, SettingsService) { +imageWriter.service('ImageWriterService', function($q, $timeout, SettingsService, NotifierService) { let self = this; let burning = false; + /** + * @summary Reset burn state + * @function + * @public + * + * @example + * ImageWriterService.resetState(); + */ + this.resetState = function() { + self.state = { + progress: 0, + speed: 0 + }; + }; + + /** + * @summary Burn progress state + * @type Object + * @public + */ + this.state = {}; + this.resetState(); + /** * @summary Check if currently burning * @function @@ -102,11 +127,10 @@ imageWriter.service('ImageWriterService', function($q, $timeout, SettingsService * @public * * @description - * This function will update `state.progress` with the current writing percentage. + * This function will update `ImageWriterService.state` with the current writing state. * * @param {String} image - image path * @param {Object} drive - drive - * @param {Function} onProgress - in progress callback (state) * * @returns {Promise} * @@ -117,7 +141,7 @@ imageWriter.service('ImageWriterService', function($q, $timeout, SettingsService * console.log('Write completed!'); * }); */ - this.burn = function(image, drive, onProgress) { + this.burn = function(image, drive) { if (self.isBurning()) { return $q.reject(new Error('There is already a burn in progress')); } @@ -129,13 +153,14 @@ imageWriter.service('ImageWriterService', function($q, $timeout, SettingsService // Safely bring the state to the world of Angular $timeout(function() { - return onProgress({ + self.state = { progress: Math.floor(state.percentage), // Transform bytes to megabytes preserving only two decimal places speed: Math.floor(state.speed / 1e+6 * 100) / 100 || 0 + }; - }); + NotifierService.emit('image-writer:state', self.state); }); }).finally(function() { diff --git a/lib/partials/main.html b/lib/partials/main.html index 820d07a6..716f0324 100644 --- a/lib/partials/main.html +++ b/lib/partials/main.html @@ -56,17 +56,17 @@ 3
- - Finishing... - Burn! - Starting... - + Finishing... + Burn! + Starting... + - +
diff --git a/tests/browser/modules/image-writer.spec.js b/tests/browser/modules/image-writer.spec.js index 3bcf4bb2..7748856d 100644 --- a/tests/browser/modules/image-writer.spec.js +++ b/tests/browser/modules/image-writer.spec.js @@ -23,6 +23,35 @@ describe('Browser: ImageWriter', function() { ImageWriterService = _ImageWriterService_; })); + describe('.state', function() { + + it('should be reset by default', function() { + m.chai.expect(ImageWriterService.state).to.deep.equal({ + progress: 0, + speed: 0 + }); + }); + + }); + + describe('.resetState()', function() { + + it('should be able to reset the state', function() { + ImageWriterService.state = { + progress: 50, + speed: 3 + }; + + ImageWriterService.resetState(); + + m.chai.expect(ImageWriterService.state).to.deep.equal({ + progress: 0, + speed: 0 + }); + }); + + }); + describe('.isBurning()', function() { it('should return false by default', function() {