mirror of
https://github.com/balena-io/etcher.git
synced 2025-07-22 18:56:31 +00:00
feat(GUI): add button to cancel flash process (#2301)
We add a cancel button next to the flash progress bar that gracefully aborts the flash process. Closes: https://github.com/resin-io/etcher/issues/1791 Closes: https://github.com/resin-io/etcher/issues/2234 Closes: https://github.com/resin-io/etcher/issues/2245 Change-Type: patch Changelog-Entry: Add a button to cancel the flash process.
This commit is contained in:
parent
71064cc760
commit
674019ea75
@ -30,6 +30,7 @@ const permissions = require('../../../shared/permissions')
|
|||||||
const windowProgress = require('../os/window-progress')
|
const windowProgress = require('../os/window-progress')
|
||||||
const analytics = require('../modules/analytics')
|
const analytics = require('../modules/analytics')
|
||||||
const packageJSON = require('../../../../package.json')
|
const packageJSON = require('../../../../package.json')
|
||||||
|
const selectionState = require('../../../shared/models/selection-state')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @summary Number of threads per CPU to allocate to the UV_THREADPOOL
|
* @summary Number of threads per CPU to allocate to the UV_THREADPOOL
|
||||||
@ -175,6 +176,13 @@ exports.performWrite = (image, drives, onProgress) => {
|
|||||||
_.merge(flashResults, event)
|
_.merge(flashResults, event)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
ipc.server.on('abort', () => {
|
||||||
|
terminateServer()
|
||||||
|
resolve({
|
||||||
|
cancelled: true
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
ipc.server.on('state', onProgress)
|
ipc.server.on('state', onProgress)
|
||||||
|
|
||||||
ipc.server.on('ready', (data, socket) => {
|
ipc.server.on('ready', (data, socket) => {
|
||||||
@ -321,3 +329,28 @@ exports.flash = (image, drives) => {
|
|||||||
windowProgress.clear()
|
windowProgress.clear()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @summary Cancel write operation
|
||||||
|
* @function
|
||||||
|
* @public
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* imageWriter.cancel()
|
||||||
|
*/
|
||||||
|
exports.cancel = () => {
|
||||||
|
analytics.logEvent('Cancel', {
|
||||||
|
image: selectionState.getImagePath(),
|
||||||
|
drives: selectionState.getSelectedDevices(),
|
||||||
|
uuid: flashState.getFlashUuid(),
|
||||||
|
unmountOnSuccess: settings.get('unmountOnSuccess'),
|
||||||
|
validateWriteOnSuccess: settings.get('validateWriteOnSuccess')
|
||||||
|
})
|
||||||
|
|
||||||
|
try {
|
||||||
|
const [ socket ] = ipc.server.sockets
|
||||||
|
ipc.server.emit(socket, 'cancel')
|
||||||
|
} catch (error) {
|
||||||
|
analytics.logException(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -209,4 +209,14 @@ module.exports = function (
|
|||||||
|
|
||||||
return progressStatus.fromFlashState(flashState.getFlashState())
|
return progressStatus.fromFlashState(flashState.getFlashState())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @summary Abort write process
|
||||||
|
* @function
|
||||||
|
* @public
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* FlashController.cancelFlash()
|
||||||
|
*/
|
||||||
|
this.cancelFlash = imageWriter.cancel
|
||||||
}
|
}
|
||||||
|
@ -41,6 +41,10 @@ svg-icon > img[disabled] {
|
|||||||
min-width: $btn-min-width;
|
min-width: $btn-min-width;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.page-main .button-abort-write {
|
||||||
|
margin-right: -35px;
|
||||||
|
}
|
||||||
|
|
||||||
%step-border {
|
%step-border {
|
||||||
height: 2px;
|
height: 2px;
|
||||||
background-color: $palette-theme-dark-foreground;
|
background-color: $palette-theme-dark-foreground;
|
||||||
|
@ -106,6 +106,12 @@
|
|||||||
<span ng-bind="flash.getProgressButtonLabel()"></span>
|
<span ng-bind="flash.getProgressButtonLabel()"></span>
|
||||||
</progress-button>
|
</progress-button>
|
||||||
|
|
||||||
|
<button class="button button-link button-abort-write"
|
||||||
|
ng-if="main.state.isFlashing()"
|
||||||
|
ng-click="flash.cancelFlash()">
|
||||||
|
<span class="glyphicon glyphicon-remove-sign"></span>
|
||||||
|
</button>
|
||||||
|
|
||||||
<p class="step-footer step-footer-split" ng-if="main.state.getFlashState().speed && main.state.getFlashState().percentage != 100">
|
<p class="step-footer step-footer-split" ng-if="main.state.getFlashState().speed && main.state.getFlashState().percentage != 100">
|
||||||
<span ng-bind="main.state.getFlashState().speed.toFixed(2) + ' MB/s'"></span>
|
<span ng-bind="main.state.getFlashState().speed.toFixed(2) + ' MB/s'"></span>
|
||||||
<span>ETA: {{ main.state.getFlashState().eta | secondsToDate | amDateFormat:'m[m]ss[s]' }}</span>
|
<span>ETA: {{ main.state.getFlashState().eta | secondsToDate | amDateFormat:'m[m]ss[s]' }}</span>
|
||||||
|
@ -6523,6 +6523,9 @@ svg-icon > img[disabled] {
|
|||||||
.page-main .button-brick {
|
.page-main .button-brick {
|
||||||
min-width: 170px; }
|
min-width: 170px; }
|
||||||
|
|
||||||
|
.page-main .button-abort-write {
|
||||||
|
margin-right: -35px; }
|
||||||
|
|
||||||
.page-main .step-border-left, .page-main .step-border-right {
|
.page-main .step-border-left, .page-main .step-border-right {
|
||||||
height: 2px;
|
height: 2px;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
|
@ -111,6 +111,8 @@ ipc.connectTo(IPC_SERVER_ID, () => {
|
|||||||
terminate(EXIT_CODES.SUCCESS)
|
terminate(EXIT_CODES.SUCCESS)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
let writer = null
|
||||||
|
|
||||||
ipc.of[IPC_SERVER_ID].on('write', (options) => {
|
ipc.of[IPC_SERVER_ID].on('write', (options) => {
|
||||||
const destinations = [].concat(options.destinations)
|
const destinations = [].concat(options.destinations)
|
||||||
|
|
||||||
@ -146,6 +148,17 @@ ipc.connectTo(IPC_SERVER_ID, () => {
|
|||||||
terminate(exitCode)
|
terminate(exitCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @summary Abort handler
|
||||||
|
* @example
|
||||||
|
* writer.on('abort', onAbort)
|
||||||
|
*/
|
||||||
|
const onAbort = () => {
|
||||||
|
log('Abort')
|
||||||
|
ipc.of[IPC_SERVER_ID].emit('abort')
|
||||||
|
terminate(exitCode)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @summary Error handler
|
* @summary Error handler
|
||||||
* @param {Error} error - error
|
* @param {Error} error - error
|
||||||
@ -171,7 +184,7 @@ ipc.connectTo(IPC_SERVER_ID, () => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const writer = new ImageWriter({
|
writer = new ImageWriter({
|
||||||
verify: options.validateWriteOnSuccess,
|
verify: options.validateWriteOnSuccess,
|
||||||
unmountOnSuccess: options.unmountOnSuccess,
|
unmountOnSuccess: options.unmountOnSuccess,
|
||||||
checksumAlgorithms: options.checksumAlgorithms || []
|
checksumAlgorithms: options.checksumAlgorithms || []
|
||||||
@ -181,10 +194,17 @@ ipc.connectTo(IPC_SERVER_ID, () => {
|
|||||||
writer.on('fail', onFail)
|
writer.on('fail', onFail)
|
||||||
writer.on('progress', onProgress)
|
writer.on('progress', onProgress)
|
||||||
writer.on('finish', onFinish)
|
writer.on('finish', onFinish)
|
||||||
|
writer.on('abort', onAbort)
|
||||||
|
|
||||||
writer.write(options.imagePath, destinations)
|
writer.write(options.imagePath, destinations)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
ipc.of[IPC_SERVER_ID].on('cancel', () => {
|
||||||
|
if (writer) {
|
||||||
|
writer.abort()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
ipc.of[IPC_SERVER_ID].on('connect', () => {
|
ipc.of[IPC_SERVER_ID].on('connect', () => {
|
||||||
log(`Successfully connected to IPC server: ${IPC_SERVER_ID}, socket root ${ipc.config.socketRoot}`)
|
log(`Successfully connected to IPC server: ${IPC_SERVER_ID}, socket root ${ipc.config.socketRoot}`)
|
||||||
ipc.of[IPC_SERVER_ID].emit('ready', {})
|
ipc.of[IPC_SERVER_ID].emit('ready', {})
|
||||||
|
@ -4,3 +4,4 @@ rules:
|
|||||||
no-param-reassign: off
|
no-param-reassign: off
|
||||||
no-underscore-dangle: off
|
no-underscore-dangle: off
|
||||||
lodash/prefer-lodash-method: off
|
lodash/prefer-lodash-method: off
|
||||||
|
lodash/prefer-get: off
|
||||||
|
@ -568,8 +568,8 @@ class ImageWriter extends EventEmitter {
|
|||||||
* imageWriter.abort()
|
* imageWriter.abort()
|
||||||
*/
|
*/
|
||||||
abort () {
|
abort () {
|
||||||
if (this.source) {
|
if (this.source && this.source.stream) {
|
||||||
this.source.destroy()
|
this.source.stream.destroy()
|
||||||
}
|
}
|
||||||
this.emit('abort')
|
this.emit('abort')
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user