mirror of
https://github.com/balena-io/etcher.git
synced 2025-04-24 15:27:17 +00:00
feat(GUI): warn the user on large drive selection (#2045)
We warn the user when they select a large drive to confirm they want to flash in case the device is important. Fixes: https://github.com/resin-io/etcher/issues/1916 Change-Type: patch Changelog-Entry: Warn the user on selection of large drives.
This commit is contained in:
parent
b1b82301d9
commit
91719435d9
@ -75,17 +75,24 @@ module.exports = function (
|
||||
return $q.resolve(false)
|
||||
}
|
||||
|
||||
if (constraints.isDriveSizeRecommended(drive, selectionState.getImage())) {
|
||||
return $q.resolve(true)
|
||||
if (!constraints.isDriveSizeRecommended(drive, selectionState.getImage())) {
|
||||
return WarningModalService.display({
|
||||
confirmationLabel: 'Yes, continue',
|
||||
description: [
|
||||
messages.warning.unrecommendedDriveSize(selectionState.getImage(), drive),
|
||||
'Are you sure you want to continue?'
|
||||
].join(' ')
|
||||
})
|
||||
}
|
||||
|
||||
return WarningModalService.display({
|
||||
confirmationLabel: 'Yes, continue',
|
||||
description: [
|
||||
messages.warning.unrecommendedDriveSize(selectionState.getImage(), drive),
|
||||
'Are you sure you want to continue?'
|
||||
].join(' ')
|
||||
})
|
||||
if (constraints.isDriveSizeLarge(drive)) {
|
||||
return WarningModalService.display({
|
||||
confirmationLabel: 'Yes, continue',
|
||||
description: messages.warning.largeDriveSize(drive)
|
||||
})
|
||||
}
|
||||
|
||||
return $q.resolve(true)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -276,6 +276,29 @@ exports.isDriveSizeRecommended = (drive, image) => {
|
||||
return _.get(drive, [ 'size' ], UNKNOWN_SIZE) >= _.get(image, [ 'recommendedDriveSize' ], UNKNOWN_SIZE)
|
||||
}
|
||||
|
||||
/**
|
||||
* @summary 64GB
|
||||
* @private
|
||||
* @constant
|
||||
*/
|
||||
exports.LARGE_DRIVE_SIZE = 64e9
|
||||
|
||||
/**
|
||||
* @summary Check whether a drive's size is 'large'
|
||||
* @public
|
||||
*
|
||||
* @param {Object} drive - drive
|
||||
* @returns {Boolean} whether drive size is large
|
||||
*
|
||||
* @example
|
||||
* if (constraints.isDriveSizeLarge(drive)) {
|
||||
* console.log('Impressive')
|
||||
* }
|
||||
*/
|
||||
exports.isDriveSizeLarge = (drive) => {
|
||||
return _.get(drive, [ 'size' ], UNKNOWN_SIZE) > exports.LARGE_DRIVE_SIZE
|
||||
}
|
||||
|
||||
/**
|
||||
* @summary Drive/image compatibility status messages.
|
||||
* @public
|
||||
@ -330,7 +353,16 @@ exports.COMPATIBILITY_STATUS_MESSAGES = {
|
||||
* @description
|
||||
* The drive contains the image and therefore cannot be written to.
|
||||
*/
|
||||
CONTAINS_IMAGE: 'Drive Contains Image'
|
||||
CONTAINS_IMAGE: 'Drive Contains Image',
|
||||
|
||||
/**
|
||||
* @property {String} LARGE_DRIVE
|
||||
* @memberof COMPATIBILITY_STATUS_MESSAGES
|
||||
*
|
||||
* @description
|
||||
* The drive is large and therefore likely not a medium you want to write to.
|
||||
*/
|
||||
LARGE_DRIVE: 'Large Drive'
|
||||
}
|
||||
|
||||
/**
|
||||
@ -416,6 +448,13 @@ exports.getDriveImageCompatibilityStatuses = (drive, image) => {
|
||||
})
|
||||
}
|
||||
|
||||
if (exports.isDriveSizeLarge(drive)) {
|
||||
statusList.push({
|
||||
type: exports.COMPATIBILITY_STATUS_TYPES.WARNING,
|
||||
message: exports.COMPATIBILITY_STATUS_MESSAGES.LARGE_DRIVE
|
||||
})
|
||||
}
|
||||
|
||||
if (!_.isNil(drive) && !exports.isDriveSizeRecommended(drive, image)) {
|
||||
statusList.push({
|
||||
type: exports.COMPATIBILITY_STATUS_TYPES.WARNING,
|
||||
|
@ -78,6 +78,13 @@ module.exports = {
|
||||
'The image does not appear to contain a partition table,',
|
||||
'and might not be recognized or bootable by your device.'
|
||||
].join(' ')
|
||||
},
|
||||
|
||||
largeDriveSize: (drive) => {
|
||||
return [
|
||||
`Drive ${drive.description} (${drive.device}) is unusually large for an SD card or USB stick.`,
|
||||
'\n\nAre you sure you want to flash this drive?'
|
||||
].join(' ')
|
||||
}
|
||||
|
||||
},
|
||||
|
@ -144,6 +144,9 @@ const storeReducer = (state = DEFAULT_STATE, action) => {
|
||||
constraints.isDriveValid(drive, image),
|
||||
constraints.isDriveSizeRecommended(drive, image),
|
||||
|
||||
// We don't want to auto-select large drives
|
||||
!constraints.isDriveSizeLarge(drive),
|
||||
|
||||
// We don't want to auto-select system drives,
|
||||
// even when "unsafe mode" is enabled
|
||||
!constraints.isSystemDrive(drive)
|
||||
|
@ -946,6 +946,48 @@ describe('Shared: DriveConstraints', function () {
|
||||
})
|
||||
})
|
||||
|
||||
describe('.isDriveSizeLarge()', function () {
|
||||
beforeEach(function () {
|
||||
this.drive = {
|
||||
device: '/dev/disk2',
|
||||
name: 'My Drive',
|
||||
isReadonly: false,
|
||||
isSystem: false,
|
||||
disabled: false,
|
||||
mountpoints: [
|
||||
{
|
||||
path: this.mountpoint
|
||||
}
|
||||
],
|
||||
size: constraints.LARGE_DRIVE_SIZE + 1
|
||||
}
|
||||
|
||||
this.image = {
|
||||
path: path.join(__dirname, 'rpi.img'),
|
||||
size: {
|
||||
original: this.drive.size - 1,
|
||||
final: {
|
||||
estimation: false,
|
||||
value: this.drive.size - 1
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
describe('given a drive bigger than the unusually large drive size', function () {
|
||||
it('should return true', function () {
|
||||
m.chai.expect(constraints.isDriveSizeLarge(this.drive)).to.be.true
|
||||
})
|
||||
})
|
||||
|
||||
describe('given a drive smaller than the unusually large drive size', function () {
|
||||
it('should return false', function () {
|
||||
this.drive.size = constraints.LARGE_DRIVE_SIZE - 1
|
||||
m.chai.expect(constraints.isDriveSizeLarge(this.drive)).to.be.false
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('.getDriveImageCompatibilityStatuses', function () {
|
||||
beforeEach(function () {
|
||||
if (process.platform === 'win32') {
|
||||
@ -1080,6 +1122,17 @@ describe('Shared: DriveConstraints', function () {
|
||||
})
|
||||
})
|
||||
|
||||
describe('given the drive is unusually large', function () {
|
||||
it('should return the large drive size warning', function () {
|
||||
this.drive.size = constraints.LARGE_DRIVE_SIZE + 1
|
||||
|
||||
const result = constraints.getDriveImageCompatibilityStatuses(this.drive, this.image)
|
||||
const expectedTuples = [ [ 'WARNING', 'LARGE_DRIVE' ] ]
|
||||
|
||||
expectStatusTypesAndMessagesToBe(result, expectedTuples)
|
||||
})
|
||||
})
|
||||
|
||||
describe('given the image is null', () => {
|
||||
it('should return an empty list', function () {
|
||||
const result = constraints.getDriveImageCompatibilityStatuses(this.drive, null)
|
||||
|
@ -20,6 +20,7 @@ const m = require('mochainon')
|
||||
const path = require('path')
|
||||
const availableDrives = require('../../../lib/shared/models/available-drives')
|
||||
const selectionState = require('../../../lib/shared/models/selection-state')
|
||||
const constraints = require('../../../lib/shared/drive-constraints')
|
||||
|
||||
describe('Model: availableDrives', function () {
|
||||
describe('availableDrives', function () {
|
||||
@ -347,6 +348,27 @@ describe('Model: availableDrives', function () {
|
||||
|
||||
m.chai.expect(selectionState.hasDrive()).to.be.false
|
||||
})
|
||||
|
||||
it('should not auto-select a single large size drive', function () {
|
||||
m.chai.expect(selectionState.hasDrive()).to.be.false
|
||||
|
||||
availableDrives.setDrives([
|
||||
{
|
||||
device: '/dev/sdb',
|
||||
name: 'Foo',
|
||||
size: constraints.LARGE_DRIVE_SIZE + 1,
|
||||
mountpoints: [
|
||||
{
|
||||
path: '/mnt/foo'
|
||||
}
|
||||
],
|
||||
system: false,
|
||||
protected: false
|
||||
}
|
||||
])
|
||||
|
||||
m.chai.expect(selectionState.hasDrive()).to.be.false
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
Loading…
x
Reference in New Issue
Block a user