mirror of
https://github.com/balena-io/etcher.git
synced 2025-04-24 07:17:18 +00:00
feat(GUI): warn when atempting to burn Windows images (#1043)
Change-Type: minor Changelog-Entry: Show warning when user tries to flash a Windows image Closes: https://github.com/resin-io/etcher/issues/1035
This commit is contained in:
parent
d845cccff5
commit
5b9104e8aa
@ -18,7 +18,7 @@
|
||||
|
||||
const _ = require('lodash');
|
||||
|
||||
module.exports = function(ModalService) {
|
||||
module.exports = function($sce, ModalService) {
|
||||
|
||||
/**
|
||||
* @summary Display the warning modal
|
||||
@ -39,6 +39,7 @@ module.exports = function(ModalService) {
|
||||
* });
|
||||
*/
|
||||
this.display = (options = {}) => {
|
||||
options.description = $sce.trustAsHtml(options.description);
|
||||
return ModalService.open({
|
||||
template: './components/warning-modal/templates/warning-modal.tpl.html',
|
||||
controller: 'WarningModalController as modal',
|
||||
|
@ -7,7 +7,7 @@
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
<p>{{ ::modal.options.description }}</p>
|
||||
<p ng-bind-html="modal.options.description"></p>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
|
@ -107,15 +107,15 @@ SupportedFormats.service('SupportedFormatsModel', function() {
|
||||
* @function
|
||||
* @public
|
||||
*
|
||||
* @param {String} image - image path
|
||||
* @param {String} imagePath - image path
|
||||
* @returns {Boolean} whether the image is supported
|
||||
*
|
||||
* if (SupportedFormatsModel.isSupportedImage('foo.iso.bz2')) {
|
||||
* console.log('The image is supported!');
|
||||
* }
|
||||
*/
|
||||
this.isSupportedImage = (image) => {
|
||||
const extension = path.extname(image).slice(1).toLowerCase();
|
||||
this.isSupportedImage = (imagePath) => {
|
||||
const extension = path.extname(imagePath).slice(1).toLowerCase();
|
||||
|
||||
if (_.some([
|
||||
_.includes(this.getNonCompressedExtensions(), extension),
|
||||
@ -128,7 +128,25 @@ SupportedFormats.service('SupportedFormatsModel', function() {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.isSupportedImage(path.basename(image, `.${extension}`));
|
||||
return this.isSupportedImage(path.basename(imagePath, `.${extension}`));
|
||||
};
|
||||
|
||||
/**
|
||||
* @summary Check if an image seems to be a Windows image
|
||||
* @function
|
||||
* @public
|
||||
*
|
||||
* @param {String} imagePath - image path
|
||||
* @returns {Boolean} whether the image seems to be a Windows image
|
||||
*
|
||||
* @example
|
||||
* if (SupportedFormatsModel.looksLikeWindowsImage('path/to/en_windows_7_ultimate_with_sp1_x86_dvd_u_677460.iso')) {
|
||||
* console.log('Looks like a Windows image');
|
||||
* }
|
||||
*/
|
||||
this.looksLikeWindowsImage = (imagePath) => {
|
||||
const regex = /windows|win7|win8|win10|winxp/i;
|
||||
return regex.test(path.basename(imagePath));
|
||||
};
|
||||
|
||||
});
|
||||
|
@ -21,9 +21,25 @@
|
||||
*/
|
||||
|
||||
const angular = require('angular');
|
||||
const url = require('url');
|
||||
|
||||
const MODULE_NAME = 'Etcher.OS.OpenExternal';
|
||||
const OSOpenExternal = angular.module(MODULE_NAME, []);
|
||||
OSOpenExternal.service('OSOpenExternalService', require('./services/open-external'));
|
||||
OSOpenExternal.directive('osOpenExternal', require('./directives/open-external'));
|
||||
|
||||
OSOpenExternal.run(function(OSOpenExternalService) {
|
||||
document.addEventListener('click', (event) => {
|
||||
const target = event.target;
|
||||
if (target.tagName === 'A' && angular.isDefined(target.href)) {
|
||||
|
||||
// Electron interprets relative URLs as being relative to the current loaded URL (with `webContents.loadURL`) and expands
|
||||
// them to the corresponding absolute URL. If it's a `file://` URL, we don't want it opened in an external browser.
|
||||
if (url.parse(target.href).protocol !== 'file:') {
|
||||
OSOpenExternalService.open(target.href);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
module.exports = MODULE_NAME;
|
||||
|
@ -17,9 +17,17 @@
|
||||
'use strict';
|
||||
|
||||
const _ = require('lodash');
|
||||
const Bluebird = require('bluebird');
|
||||
const messages = require('../../../../shared/messages');
|
||||
|
||||
module.exports = function(SupportedFormatsModel, SelectionStateModel, AnalyticsService, ErrorService, OSDialogService) {
|
||||
module.exports = function(
|
||||
SupportedFormatsModel,
|
||||
SelectionStateModel,
|
||||
AnalyticsService,
|
||||
ErrorService,
|
||||
OSDialogService,
|
||||
WarningModalService
|
||||
) {
|
||||
|
||||
/**
|
||||
* @summary Main supported extensions
|
||||
@ -65,14 +73,36 @@ module.exports = function(SupportedFormatsModel, SelectionStateModel, AnalyticsS
|
||||
return;
|
||||
}
|
||||
|
||||
SelectionStateModel.setImage(image);
|
||||
Bluebird.try(() => {
|
||||
if (!SupportedFormatsModel.looksLikeWindowsImage(image.path)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// An easy way so we can quickly identify if we're making use of
|
||||
// certain features without printing pages of text to DevTools.
|
||||
image.logo = Boolean(image.logo);
|
||||
image.bmap = Boolean(image.bmap);
|
||||
AnalyticsService.logEvent('Possibly Windows image', image);
|
||||
|
||||
// TODO: `Continue` should be on a red background (dangerous action) instead of `Change`.
|
||||
// We want `X` to act as `Continue`, that's why `Continue` is the `rejectionLabel`
|
||||
return WarningModalService.display({
|
||||
confirmationLabel: 'Change',
|
||||
rejectionLabel: 'Continue',
|
||||
description: messages.warning.looksLikeWindowsImage()
|
||||
});
|
||||
}).then((shouldChange) => {
|
||||
|
||||
if (shouldChange) {
|
||||
return this.reselectImage();
|
||||
}
|
||||
|
||||
SelectionStateModel.setImage(image);
|
||||
|
||||
// An easy way so we can quickly identify if we're making use of
|
||||
// certain features without printing pages of text to DevTools.
|
||||
image.logo = Boolean(image.logo);
|
||||
image.bmap = Boolean(image.bmap);
|
||||
|
||||
AnalyticsService.logEvent('Select image', image);
|
||||
}).catch(ErrorService.reportException);
|
||||
|
||||
AnalyticsService.logEvent('Select image', image);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -51,6 +51,13 @@ module.exports = {
|
||||
exitWhileFlashing: _.template([
|
||||
'You are currently flashing a drive.',
|
||||
'Closing Etcher may leave your drive in an unusable state.'
|
||||
].join(' ')),
|
||||
|
||||
looksLikeWindowsImage: _.template([
|
||||
'It looks like you are trying to burn a Windows image.\n\n',
|
||||
'Unlike other images, Windows images require special processing to be made bootable.',
|
||||
'We suggest you use a tool specially designed for this purpose, such as',
|
||||
'<a href="https://rufus.akeo.ie">Rufus</a>.'
|
||||
].join(' '))
|
||||
|
||||
},
|
||||
|
@ -123,6 +123,36 @@ describe('Browser: SupportedFormats', function() {
|
||||
|
||||
});
|
||||
|
||||
describe('.looksLikeWindowsImage()', function() {
|
||||
|
||||
_.each([
|
||||
'C:\\path\\to\\en_windows_10_multiple_editions_version_1607_updated_jan_2017_x64_dvd_9714399.iso',
|
||||
'/path/to/en_windows_10_multiple_editions_version_1607_updated_jan_2017_x64_dvd_9714399.iso',
|
||||
'/path/to/Win10_1607_SingleLang_English_x32.iso',
|
||||
'/path/to/en_winxp_pro_x86_build2600_iso.img'
|
||||
], (imagePath) => {
|
||||
|
||||
it(`should return true if filename is ${imagePath}`, function() {
|
||||
const looksLikeWindowsImage = SupportedFormatsModel.looksLikeWindowsImage(imagePath);
|
||||
m.chai.expect(looksLikeWindowsImage).to.be.true;
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
_.each([
|
||||
'C:\\path\\to\\2017-01-11-raspbian-jessie.img',
|
||||
'/path/to/2017-01-11-raspbian-jessie.img'
|
||||
], (imagePath) => {
|
||||
|
||||
it(`should return false if filename is ${imagePath}`, function() {
|
||||
const looksLikeWindowsImage = SupportedFormatsModel.looksLikeWindowsImage(imagePath);
|
||||
m.chai.expect(looksLikeWindowsImage).to.be.false;
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user