mirror of
https://github.com/balena-io/etcher.git
synced 2025-07-26 20:56:34 +00:00
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:
parent
54909d267d
commit
004a965c33
@ -97,7 +97,7 @@ app.run((AnalyticsService, UpdateNotifierService, SelectionStateModel) => {
|
|||||||
|
|
||||||
app.run((AnalyticsService, OSWindowProgressService, ImageWriterService) => {
|
app.run((AnalyticsService, OSWindowProgressService, ImageWriterService) => {
|
||||||
Store.subscribe(() => {
|
Store.subscribe(() => {
|
||||||
const state = Store.getState().toJS();
|
const flashState = ImageWriterService.getFlashState();
|
||||||
|
|
||||||
// There is usually a short time period between the `isFlashing()`
|
// There is usually a short time period between the `isFlashing()`
|
||||||
// property being set, and the flashing actually starting, which
|
// 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
|
// We use the presence of `.eta` to determine that the actual
|
||||||
// writing started.
|
// writing started.
|
||||||
if (!ImageWriterService.isFlashing() || !state.flashState.eta) {
|
if (!ImageWriterService.isFlashing() || !flashState.eta) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
AnalyticsService.log([
|
AnalyticsService.log([
|
||||||
`Progress (${state.flashState.type}):`,
|
`Progress (${flashState.type}):`,
|
||||||
`${state.flashState.percentage}% at ${state.flashState.speed} MB/s`,
|
`${flashState.percentage}% at ${flashState.speed} MB/s`,
|
||||||
`(eta ${state.flashState.eta}s)`
|
`(eta ${flashState.eta}s)`
|
||||||
].join(' '));
|
].join(' '));
|
||||||
|
|
||||||
OSWindowProgressService.set(state.flashState.percentage);
|
OSWindowProgressService.set(flashState.percentage);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -133,7 +133,6 @@ app.config(($stateProvider, $urlRouterProvider) => {
|
|||||||
|
|
||||||
app.controller('AppController', function(
|
app.controller('AppController', function(
|
||||||
$state,
|
$state,
|
||||||
$scope,
|
|
||||||
DriveScannerService,
|
DriveScannerService,
|
||||||
SelectionStateModel,
|
SelectionStateModel,
|
||||||
SettingsModel,
|
SettingsModel,
|
||||||
|
@ -30,7 +30,7 @@ const imageWriter = angular.module(MODULE_NAME, [
|
|||||||
require('../models/settings')
|
require('../models/settings')
|
||||||
]);
|
]);
|
||||||
|
|
||||||
imageWriter.service('ImageWriterService', function($q, $timeout, SettingsModel) {
|
imageWriter.service('ImageWriterService', function($q, $rootScope, SettingsModel) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @summary Reset flash state
|
* @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
|
* @summary Check if currently flashing
|
||||||
* @function
|
* @function
|
||||||
@ -179,6 +160,20 @@ imageWriter.service('ImageWriterService', function($q, $timeout, SettingsModel)
|
|||||||
return Store.getState().toJS().flashResults;
|
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
|
* @summary Perform write operation
|
||||||
* @function
|
* @function
|
||||||
@ -239,7 +234,17 @@ imageWriter.service('ImageWriterService', function($q, $timeout, SettingsModel)
|
|||||||
|
|
||||||
this.setFlashingFlag();
|
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
|
// TODO: Make sure `etcher-image-write` always
|
||||||
// sends a `cancelled` and `passedValidation` property.
|
// sends a `cancelled` and `passedValidation` property.
|
||||||
|
@ -84,19 +84,19 @@
|
|||||||
|
|
||||||
<div class="space-vertical-large">
|
<div class="space-vertical-large">
|
||||||
<progress-button class="btn-brick"
|
<progress-button class="btn-brick"
|
||||||
percentage="app.writer.state.percentage"
|
percentage="app.writer.getFlashState().percentage"
|
||||||
striped="{{ app.writer.state.type == 'check' }}"
|
striped="{{ app.writer.getFlashState().type == 'check' }}"
|
||||||
ng-attr-active="{{ app.writer.isFlashing() }}"
|
ng-attr-active="{{ app.writer.isFlashing() }}"
|
||||||
ng-show="app.wasLastFlashSuccessful()"
|
ng-show="app.wasLastFlashSuccessful()"
|
||||||
ng-click="app.flash(app.selection.getImagePath(), app.selection.getDrive())"
|
ng-click="app.flash(app.selection.getImagePath(), app.selection.getDrive())"
|
||||||
ng-disabled="!app.selection.hasImage() || !app.selection.hasDrive()">
|
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.getFlashState().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.getFlashState().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.getFlashState().percentage == 0 && app.writer.isFlashing() && !app.writer.getFlashState().speed">Starting...</span>
|
||||||
<span ng-show="app.writer.state.speed && app.writer.state.percentage != 100 && app.writer.state.type != 'check'"
|
<span ng-show="app.writer.getFlashState().speed && app.writer.getFlashState().percentage != 100 && app.writer.getFlashState().type != 'check'"
|
||||||
ng-bind="app.writer.state.percentage + '% '"></span>
|
ng-bind="app.writer.getFlashState().percentage + '% '"></span>
|
||||||
<span ng-show="app.writer.state.speed && app.writer.state.percentage != 100 && app.writer.state.type == 'check'"
|
<span ng-show="app.writer.getFlashState().speed && app.writer.getFlashState().percentage != 100 && app.writer.getFlashState().type == 'check'"
|
||||||
ng-bind="app.writer.state.percentage + '% Validating...'"></span>
|
ng-bind="app.writer.getFlashState().percentage + '% Validating...'"></span>
|
||||||
</progress-button>
|
</progress-button>
|
||||||
|
|
||||||
<div class="alert-ribbon alert-warning" ng-class="{ 'alert-ribbon--open': !app.wasLastFlashSuccessful() }">
|
<div class="alert-ribbon alert-warning" ng-class="{ 'alert-ribbon--open': !app.wasLastFlashSuccessful() }">
|
||||||
@ -116,9 +116,9 @@
|
|||||||
<span class="glyphicon glyphicon-repeat"></span> Retry
|
<span class="glyphicon glyphicon-repeat"></span> Retry
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<p class="step-footer step-footer-split" ng-show="app.writer.state.speed && app.writer.state.percentage != 100">
|
<p class="step-footer step-footer-split" ng-show="app.writer.getFlashState().speed && app.writer.getFlashState().percentage != 100">
|
||||||
<span>ETA: {{ app.writer.state.eta | secondsToDate | amDateFormat:'m[m]ss[s]' }}</span>
|
<span>ETA: {{ app.writer.getFlashState().eta | secondsToDate | amDateFormat:'m[m]ss[s]' }}</span>
|
||||||
<span ng-bind="app.writer.state.speed.toFixed(2) + ' MB/s'"></span>
|
<span ng-bind="app.writer.getFlashState().speed.toFixed(2) + ' MB/s'"></span>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -13,40 +13,29 @@ describe('Browser: ImageWriter', function() {
|
|||||||
describe('ImageWriterService', function() {
|
describe('ImageWriterService', function() {
|
||||||
|
|
||||||
let $q;
|
let $q;
|
||||||
let $timeout;
|
|
||||||
let $rootScope;
|
let $rootScope;
|
||||||
let ImageWriterService;
|
let ImageWriterService;
|
||||||
|
|
||||||
beforeEach(angular.mock.inject(function(_$q_, _$timeout_, _$rootScope_, _ImageWriterService_) {
|
beforeEach(angular.mock.inject(function(_$q_, _$rootScope_, _ImageWriterService_) {
|
||||||
$q = _$q_;
|
$q = _$q_;
|
||||||
$timeout = _$timeout_;
|
|
||||||
$rootScope = _$rootScope_;
|
$rootScope = _$rootScope_;
|
||||||
ImageWriterService = _ImageWriterService_;
|
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() {
|
describe('.resetState()', function() {
|
||||||
|
|
||||||
it('should be able to reset the progress state', function() {
|
it('should be able to reset the progress state', function() {
|
||||||
ImageWriterService.state = {
|
ImageWriterService.setFlashingFlag();
|
||||||
|
ImageWriterService.setProgressState({
|
||||||
|
type: 'write',
|
||||||
percentage: 50,
|
percentage: 50,
|
||||||
speed: 3
|
eta: 15,
|
||||||
};
|
speed: 100000000000
|
||||||
|
});
|
||||||
|
|
||||||
ImageWriterService.resetState();
|
ImageWriterService.resetState();
|
||||||
$timeout.flush();
|
|
||||||
|
|
||||||
m.chai.expect(ImageWriterService.state).to.deep.equal({
|
m.chai.expect(ImageWriterService.getFlashState()).to.deep.equal({
|
||||||
percentage: 0,
|
percentage: 0,
|
||||||
speed: 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() {
|
describe('.unsetFlashingFlag()', function() {
|
||||||
|
|
||||||
it('should throw if no flashing results', function() {
|
it('should throw if no flashing results', function() {
|
||||||
@ -348,9 +364,7 @@ describe('Browser: ImageWriter', function() {
|
|||||||
speed: 100000000000
|
speed: 100000000000
|
||||||
});
|
});
|
||||||
|
|
||||||
$timeout.flush();
|
m.chai.expect(ImageWriterService.getFlashState()).to.not.deep.equal({
|
||||||
|
|
||||||
m.chai.expect(ImageWriterService.state).to.not.deep.equal({
|
|
||||||
percentage: 0,
|
percentage: 0,
|
||||||
speed: 0
|
speed: 0
|
||||||
});
|
});
|
||||||
@ -361,9 +375,7 @@ describe('Browser: ImageWriter', function() {
|
|||||||
sourceChecksum: '1234'
|
sourceChecksum: '1234'
|
||||||
});
|
});
|
||||||
|
|
||||||
$timeout.flush();
|
m.chai.expect(ImageWriterService.getFlashState()).to.deep.equal({
|
||||||
|
|
||||||
m.chai.expect(ImageWriterService.state).to.deep.equal({
|
|
||||||
percentage: 0,
|
percentage: 0,
|
||||||
speed: 0
|
speed: 0
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user