diff --git a/lib/gui/app/pages/main/controllers/drive-selection.js b/lib/gui/app/pages/main/controllers/drive-selection.js index 9fd4f04f..97abced3 100644 --- a/lib/gui/app/pages/main/controllers/drive-selection.js +++ b/lib/gui/app/pages/main/controllers/drive-selection.js @@ -18,6 +18,7 @@ const _ = require('lodash') const angular = require('angular') +const prettyBytes = require('pretty-bytes') const settings = require('../../../models/settings') const selectionState = require('../../../../../shared/models/selection-state') const analytics = require('../../../modules/analytics') @@ -44,9 +45,35 @@ module.exports = function (DriveSelectorService) { return _.head(drives).description || 'Untitled Device' } + // eslint-disable-next-line no-magic-numbers + if (drives.length === 0) { + return 'No targets found' + } + return `${drives.length} Devices` } + /** + * @summary Get drive subtitle + * @function + * @public + * + * @returns {String} - drives subtitle + * + * @example + * console.log(DriveSelectionController.getDrivesSubtitle()) + * > '32 GB' + */ + this.getDrivesSubtitle = () => { + const drive = selectionState.getCurrentDrive() + + if (drive) { + return prettyBytes(drive.size) + } + + return 'Please insert at least one target device' + } + /** * @summary Get drive list label * @function @@ -109,4 +136,18 @@ module.exports = function (DriveSelectorService) { * DriveSelectionController.getMemoizedSelectedDrives() */ this.getMemoizedSelectedDrives = utils.memoize(selectionState.getSelectedDrives, angular.equals) + + /** + * @summary Should the drive selection button be shown + * @function + * @public + * + * @returns {Boolean} + * + * @example + * DriveSelectionController.shouldShowDrivesButton() + */ + this.shouldShowDrivesButton = () => { + return !process.env.ETCHER_DISABLE_EXPLICIT_DRIVE_SELECTION + } } diff --git a/lib/gui/app/pages/main/styles/_main.scss b/lib/gui/app/pages/main/styles/_main.scss index 45e8cdce..e06fe631 100644 --- a/lib/gui/app/pages/main/styles/_main.scss +++ b/lib/gui/app/pages/main/styles/_main.scss @@ -33,6 +33,10 @@ svg-icon > img[disabled] { color: $palette-theme-dark-disabled-foreground; } +.page-main .step-drive.text-warning { + color: $palette-theme-warning-background; +} + .page-main .relative { position: relative; } @@ -123,8 +127,13 @@ svg-icon > img[disabled] { } .page-main .step-name { + display: flex; + justify-content: center; + align-items: center; + height: 39px; width: 100%; margin-right: 4.5px; + margin-bottom: 10px; font-weight: bold; color: $palette-theme-primary-foreground; } diff --git a/lib/gui/app/pages/main/templates/main.tpl.html b/lib/gui/app/pages/main/templates/main.tpl.html index 10a7b89b..a5f5e22d 100644 --- a/lib/gui/app/pages/main/templates/main.tpl.html +++ b/lib/gui/app/pages/main/templates/main.tpl.html @@ -49,7 +49,7 @@
-
+
-
+
- {{ drive.getDrivesTitle() | middleEllipsis:20 }} - {{ main.selection.getCurrentDrive().size | closestUnit }} + {{ drive.getDrivesSubtitle() }} + ng-hide="main.state.isFlashing() || !drive.shouldShowDrivesButton()" + ng-click="drive.reselectDrive()">Change
diff --git a/lib/gui/css/main.css b/lib/gui/css/main.css index 17b1173a..e4844e3f 100644 --- a/lib/gui/css/main.css +++ b/lib/gui/css/main.css @@ -6517,6 +6517,9 @@ svg-icon > img[disabled] { .page-main .text-disabled > span { color: #787c7f; } +.page-main .step-drive.text-warning { + color: #ff912f; } + .page-main .relative { position: relative; } @@ -6586,8 +6589,13 @@ svg-icon > img[disabled] { vertical-align: text-top; } .page-main .step-name { + display: flex; + justify-content: center; + align-items: center; + height: 39px; width: 100%; margin-right: 4.5px; + margin-bottom: 10px; font-weight: bold; color: #fff; } diff --git a/lib/shared/store.js b/lib/shared/store.js index b4fa9c30..2975b339 100644 --- a/lib/shared/store.js +++ b/lib/shared/store.js @@ -197,41 +197,43 @@ const storeReducer = (state = DEFAULT_STATE, action) => { return accState }, newState) + const shouldAutoselectAll = Boolean(process.env.ETCHER_DISABLE_EXPLICIT_DRIVE_SELECTION) const AUTOSELECT_DRIVE_COUNT = 1 - const numberOfDrives = drives.length const nonStaleSelectedDevices = nonStaleNewState.getIn([ 'selection', 'devices' ]).toJS() const hasSelectedDevices = nonStaleSelectedDevices.length >= AUTOSELECT_DRIVE_COUNT - if (numberOfDrives === AUTOSELECT_DRIVE_COUNT && !hasSelectedDevices) { - const [ drive ] = drives + const shouldAutoselectOne = drives.length === AUTOSELECT_DRIVE_COUNT && !hasSelectedDevices + if (shouldAutoselectOne || shouldAutoselectAll) { // Even if there's no image selected, we need to call several // drive/image related checks, and `{}` works fine with them const image = state.getIn([ 'selection', 'image' ], Immutable.fromJS({})).toJS() - if (_.every([ - constraints.isDriveValid(drive, image), - constraints.isDriveSizeRecommended(drive, image), + return _.reduce(drives, (accState, drive) => { + if (_.every([ + 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 large drives + !constraints.isDriveSizeLarge(drive), - // We don't want to auto-select system drives, - // even when "unsafe mode" is enabled - !constraints.isSystemDrive(drive) + // We don't want to auto-select system drives, + // even when "unsafe mode" is enabled + !constraints.isSystemDrive(drive) - ])) { - // Auto-select this drive - return storeReducer(nonStaleNewState, { - type: ACTIONS.SELECT_DRIVE, + ]) || (shouldAutoselectAll && constraints.isDriveValid(drive, image))) { + // Auto-select this drive + return storeReducer(accState, { + type: ACTIONS.SELECT_DRIVE, + data: drive.device + }) + } + + // Deselect this drive in case it still is selected + return storeReducer(accState, { + type: ACTIONS.DESELECT_DRIVE, data: drive.device }) - } - - // Deselect this drive in case it still is selected - return storeReducer(nonStaleNewState, { - type: ACTIONS.DESELECT_DRIVE, - data: drive.device - }) + }, nonStaleNewState) } return nonStaleNewState