refactor(GUI): stop storing flash state in a .state object variable (#604)

Currently, we subscribe to the store change events and manually update a
`.state` property in `ImageWriterService`. A much more elegant approach
is to provide a `.getFlashState()` function that fetches the flash state
directly from the store when needed.

Signed-off-by: Juan Cruz Viotti <jviottidc@gmail.com>
This commit is contained in:
Juan Cruz Viotti 2016-07-27 13:25:52 -04:00 committed by GitHub
parent 54909d267d
commit 004a965c33
4 changed files with 81 additions and 65 deletions

View File

@ -97,7 +97,7 @@ app.run((AnalyticsService, UpdateNotifierService, SelectionStateModel) => {
app.run((AnalyticsService, OSWindowProgressService, ImageWriterService) => {
Store.subscribe(() => {
const state = Store.getState().toJS();
const flashState = ImageWriterService.getFlashState();
// There is usually a short time period between the `isFlashing()`
// property being set, and the flashing actually starting, which
@ -106,17 +106,17 @@ app.run((AnalyticsService, OSWindowProgressService, ImageWriterService) => {
//
// We use the presence of `.eta` to determine that the actual
// writing started.
if (!ImageWriterService.isFlashing() || !state.flashState.eta) {
if (!ImageWriterService.isFlashing() || !flashState.eta) {
return;
}
AnalyticsService.log([
`Progress (${state.flashState.type}):`,
`${state.flashState.percentage}% at ${state.flashState.speed} MB/s`,
`(eta ${state.flashState.eta}s)`
`Progress (${flashState.type}):`,
`${flashState.percentage}% at ${flashState.speed} MB/s`,
`(eta ${flashState.eta}s)`
].join(' '));
OSWindowProgressService.set(state.flashState.percentage);
OSWindowProgressService.set(flashState.percentage);
});
});
@ -133,7 +133,6 @@ app.config(($stateProvider, $urlRouterProvider) => {
app.controller('AppController', function(
$state,
$scope,
DriveScannerService,
SelectionStateModel,
SettingsModel,

View File

@ -30,7 +30,7 @@ const imageWriter = angular.module(MODULE_NAME, [
require('../models/settings')
]);
imageWriter.service('ImageWriterService', function($q, $timeout, SettingsModel) {
imageWriter.service('ImageWriterService', function($q, $rootScope, SettingsModel) {
/**
* @summary Reset flash state
@ -46,25 +46,6 @@ imageWriter.service('ImageWriterService', function($q, $timeout, SettingsModel)
});
};
/**
* @summary Flash progress state
* @type Object
* @public
*/
this.state = {
percentage: 0,
speed: 0
};
Store.subscribe(() => {
// Safely bring the state to the world of Angular
$timeout(() => {
this.state = Store.getState().toJS().flashState;
});
});
/**
* @summary Check if currently flashing
* @function
@ -179,6 +160,20 @@ imageWriter.service('ImageWriterService', function($q, $timeout, SettingsModel)
return Store.getState().toJS().flashResults;
};
/**
* @summary Get the current flash state
* @function
* @public
*
* @returns {Object} flash state
*
* @example
* const flashState = ImageWriterService.getFlashState();
*/
this.getFlashState = () => {
return Store.getState().get('flashState').toJS();
};
/**
* @summary Perform write operation
* @function
@ -239,7 +234,17 @@ imageWriter.service('ImageWriterService', function($q, $timeout, SettingsModel)
this.setFlashingFlag();
return this.performWrite(image, drive, this.setProgressState).then((results) => {
return this.performWrite(image, drive, (state) => {
// Bring this value to the world of angular.
// If we don't trigger a digest loop,
// `.getFlashState()` will not return
// the latest updated progress state.
$rootScope.$apply(() => {
this.setProgressState(state);
});
}).then((results) => {
// TODO: Make sure `etcher-image-write` always
// sends a `cancelled` and `passedValidation` property.

View File

@ -84,19 +84,19 @@
<div class="space-vertical-large">
<progress-button class="btn-brick"
percentage="app.writer.state.percentage"
striped="{{ app.writer.state.type == 'check' }}"
percentage="app.writer.getFlashState().percentage"
striped="{{ app.writer.getFlashState().type == 'check' }}"
ng-attr-active="{{ app.writer.isFlashing() }}"
ng-show="app.wasLastFlashSuccessful()"
ng-click="app.flash(app.selection.getImagePath(), app.selection.getDrive())"
ng-disabled="!app.selection.hasImage() || !app.selection.hasDrive()">
<span ng-show="app.writer.state.percentage == 100 && app.writer.isFlashing()">Finishing...</span>
<span ng-show="app.writer.state.percentage == 0 && !app.writer.isFlashing()">Flash!</span>
<span ng-show="app.writer.state.percentage == 0 && app.writer.isFlashing() && !app.writer.state.speed">Starting...</span>
<span ng-show="app.writer.state.speed && app.writer.state.percentage != 100 && app.writer.state.type != 'check'"
ng-bind="app.writer.state.percentage + '% '"></span>
<span ng-show="app.writer.state.speed && app.writer.state.percentage != 100 && app.writer.state.type == 'check'"
ng-bind="app.writer.state.percentage + '% Validating...'"></span>
<span ng-show="app.writer.getFlashState().percentage == 100 && app.writer.isFlashing()">Finishing...</span>
<span ng-show="app.writer.getFlashState().percentage == 0 && !app.writer.isFlashing()">Flash!</span>
<span ng-show="app.writer.getFlashState().percentage == 0 && app.writer.isFlashing() && !app.writer.getFlashState().speed">Starting...</span>
<span ng-show="app.writer.getFlashState().speed && app.writer.getFlashState().percentage != 100 && app.writer.getFlashState().type != 'check'"
ng-bind="app.writer.getFlashState().percentage + '% '"></span>
<span ng-show="app.writer.getFlashState().speed && app.writer.getFlashState().percentage != 100 && app.writer.getFlashState().type == 'check'"
ng-bind="app.writer.getFlashState().percentage + '% Validating...'"></span>
</progress-button>
<div class="alert-ribbon alert-warning" ng-class="{ 'alert-ribbon--open': !app.wasLastFlashSuccessful() }">
@ -116,9 +116,9 @@
<span class="glyphicon glyphicon-repeat"></span> Retry
</button>
<p class="step-footer step-footer-split" ng-show="app.writer.state.speed && app.writer.state.percentage != 100">
<span>ETA: {{ app.writer.state.eta | secondsToDate | amDateFormat:'m[m]ss[s]' }}</span>
<span ng-bind="app.writer.state.speed.toFixed(2) + ' MB/s'"></span>
<p class="step-footer step-footer-split" ng-show="app.writer.getFlashState().speed && app.writer.getFlashState().percentage != 100">
<span>ETA: {{ app.writer.getFlashState().eta | secondsToDate | amDateFormat:'m[m]ss[s]' }}</span>
<span ng-bind="app.writer.getFlashState().speed.toFixed(2) + ' MB/s'"></span>
</p>
</div>
</div>

View File

@ -13,40 +13,29 @@ describe('Browser: ImageWriter', function() {
describe('ImageWriterService', function() {
let $q;
let $timeout;
let $rootScope;
let ImageWriterService;
beforeEach(angular.mock.inject(function(_$q_, _$timeout_, _$rootScope_, _ImageWriterService_) {
beforeEach(angular.mock.inject(function(_$q_, _$rootScope_, _ImageWriterService_) {
$q = _$q_;
$timeout = _$timeout_;
$rootScope = _$rootScope_;
ImageWriterService = _ImageWriterService_;
}));
describe('.state', function() {
it('should be reset by default', function() {
m.chai.expect(ImageWriterService.state).to.deep.equal({
percentage: 0,
speed: 0
});
});
});
describe('.resetState()', function() {
it('should be able to reset the progress state', function() {
ImageWriterService.state = {
ImageWriterService.setFlashingFlag();
ImageWriterService.setProgressState({
type: 'write',
percentage: 50,
speed: 3
};
eta: 15,
speed: 100000000000
});
ImageWriterService.resetState();
$timeout.flush();
m.chai.expect(ImageWriterService.state).to.deep.equal({
m.chai.expect(ImageWriterService.getFlashState()).to.deep.equal({
percentage: 0,
speed: 0
});
@ -233,6 +222,33 @@ describe('Browser: ImageWriter', function() {
});
describe('.getFlashState()', function() {
it('should initially return an empty state', function() {
ImageWriterService.resetState();
const flashState = ImageWriterService.getFlashState();
m.chai.expect(flashState).to.deep.equal({
percentage: 0,
speed: 0
});
});
it('should return the current flash state', function() {
const state = {
type: 'write',
percentage: 50,
eta: 15,
speed: 0
};
ImageWriterService.setFlashingFlag();
ImageWriterService.setProgressState(state);
const flashState = ImageWriterService.getFlashState();
m.chai.expect(flashState).to.deep.equal(state);
});
});
describe('.unsetFlashingFlag()', function() {
it('should throw if no flashing results', function() {
@ -348,9 +364,7 @@ describe('Browser: ImageWriter', function() {
speed: 100000000000
});
$timeout.flush();
m.chai.expect(ImageWriterService.state).to.not.deep.equal({
m.chai.expect(ImageWriterService.getFlashState()).to.not.deep.equal({
percentage: 0,
speed: 0
});
@ -361,9 +375,7 @@ describe('Browser: ImageWriter', function() {
sourceChecksum: '1234'
});
$timeout.flush();
m.chai.expect(ImageWriterService.state).to.deep.equal({
m.chai.expect(ImageWriterService.getFlashState()).to.deep.equal({
percentage: 0,
speed: 0
});