diff --git a/lib/gui/app/app.js b/lib/gui/app/app.js
index 35dd597c..d1b6a7a4 100644
--- a/lib/gui/app/app.js
+++ b/lib/gui/app/app.js
@@ -20,12 +20,6 @@
'use strict'
-/* eslint-disable no-var */
-
-var angular = require('angular')
-
-/* eslint-enable no-var */
-
const electron = require('electron')
const sdk = require('etcher-sdk')
const _ = require('lodash')
@@ -79,68 +73,51 @@ store.dispatch({
const applicationSessionUuid = store.getState().toJS().applicationSessionUuid
const flashingWorkflowUuid = store.getState().toJS().flashingWorkflowUuid
-const app = angular.module('Etcher', [
- require('angular-ui-router'),
+console.log([
+ ' _____ _ _',
+ '| ___| | | |',
+ '| |__ | |_ ___| |__ ___ _ __',
+ '| __|| __/ __| \'_ \\ / _ \\ \'__|',
+ '| |___| || (__| | | | __/ |',
+ '\\____/ \\__\\___|_| |_|\\___|_|',
+ '',
+ 'Interested in joining the Etcher team?',
+ 'Drop us a line at join+etcher@balena.io',
+ '',
+ `Version = ${packageJSON.version}, Type = ${packageJSON.packageType}`
+].join('\n'))
- // Components
- require('./components/safe-webview').MODULE_NAME,
+const currentVersion = packageJSON.version
- // Pages
- require('./pages/main/main.ts').MODULE_NAME,
- require('./components/finish/index.ts').MODULE_NAME
-])
-
-app.run(() => {
- console.log([
- ' _____ _ _',
- '| ___| | | |',
- '| |__ | |_ ___| |__ ___ _ __',
- '| __|| __/ __| \'_ \\ / _ \\ \'__|',
- '| |___| || (__| | | | __/ |',
- '\\____/ \\__\\___|_| |_|\\___|_|',
- '',
- 'Interested in joining the Etcher team?',
- 'Drop us a line at join+etcher@balena.io',
- '',
- `Version = ${packageJSON.version}, Type = ${packageJSON.packageType}`
- ].join('\n'))
+analytics.logEvent('Application start', {
+ packageType: packageJSON.packageType,
+ version: currentVersion,
+ applicationSessionUuid
})
-app.run(() => {
- const currentVersion = packageJSON.version
+store.observe(() => {
+ if (!flashState.isFlashing()) {
+ return
+ }
- analytics.logEvent('Application start', {
- packageType: packageJSON.packageType,
- version: currentVersion,
- applicationSessionUuid
- })
-})
+ const currentFlashState = flashState.getFlashState()
+ const stateType = !currentFlashState.flashing && currentFlashState.verifying
+ ? `Verifying ${currentFlashState.verifying}`
+ : `Flashing ${currentFlashState.flashing}`
-app.run(() => {
- store.observe(() => {
- if (!flashState.isFlashing()) {
- return
- }
+ // NOTE: There is usually a short time period between the `isFlashing()`
+ // property being set, and the flashing actually starting, which
+ // might cause some non-sense flashing state logs including
+ // `undefined` values.
+ analytics.logDebug(
+ `${stateType} devices, ` +
+ `${currentFlashState.percentage}% at ${currentFlashState.speed} MB/s ` +
+ `(total ${currentFlashState.totalSpeed} MB/s) ` +
+ `eta in ${currentFlashState.eta}s ` +
+ `with ${currentFlashState.failed} failed devices`
+ )
- const currentFlashState = flashState.getFlashState()
- const stateType = !currentFlashState.flashing && currentFlashState.verifying
- ? `Verifying ${currentFlashState.verifying}`
- : `Flashing ${currentFlashState.flashing}`
-
- // NOTE: There is usually a short time period between the `isFlashing()`
- // property being set, and the flashing actually starting, which
- // might cause some non-sense flashing state logs including
- // `undefined` values.
- analytics.logDebug(
- `${stateType} devices, ` +
- `${currentFlashState.percentage}% at ${currentFlashState.speed} MB/s ` +
- `(total ${currentFlashState.totalSpeed} MB/s) ` +
- `eta in ${currentFlashState.eta}s ` +
- `with ${currentFlashState.failed} failed devices`
- )
-
- windowProgress.set(currentFlashState)
- })
+ windowProgress.set(currentFlashState)
})
/**
@@ -197,242 +174,171 @@ const COMPUTE_MODULE_DESCRIPTIONS = {
[USB_PRODUCT_ID_BCM2710_BOOT]: 'Compute Module 3'
}
-app.run(($timeout) => {
- const BLACKLISTED_DRIVES = settings.has('driveBlacklist')
- ? settings.get('driveBlacklist').split(',')
- : []
+const BLACKLISTED_DRIVES = settings.has('driveBlacklist')
+ ? settings.get('driveBlacklist').split(',')
+ : []
- // eslint-disable-next-line require-jsdoc
- const driveIsAllowed = (drive) => {
- return !(
- BLACKLISTED_DRIVES.includes(drive.devicePath) ||
- BLACKLISTED_DRIVES.includes(drive.device) ||
- BLACKLISTED_DRIVES.includes(drive.raw)
- )
- }
+// eslint-disable-next-line require-jsdoc
+const driveIsAllowed = (drive) => {
+ return !(
+ BLACKLISTED_DRIVES.includes(drive.devicePath) ||
+ BLACKLISTED_DRIVES.includes(drive.device) ||
+ BLACKLISTED_DRIVES.includes(drive.raw)
+ )
+}
- // eslint-disable-next-line require-jsdoc,consistent-return
- const prepareDrive = (drive) => {
- if (drive instanceof sdk.sourceDestination.BlockDevice) {
- return drive.drive
- } else if (drive instanceof sdk.sourceDestination.UsbbootDrive) {
- // This is a workaround etcher expecting a device string and a size
- drive.device = drive.usbDevice.portId
- drive.size = null
- drive.progress = 0
- drive.disabled = true
- drive.on('progress', (progress) => {
- updateDriveProgress(drive, progress)
- })
- return drive
- } else if (drive instanceof sdk.sourceDestination.DriverlessDevice) {
- const description = COMPUTE_MODULE_DESCRIPTIONS[drive.deviceDescriptor.idProduct] || 'Compute Module'
- return {
- device: `${usbIdToString(drive.deviceDescriptor.idVendor)}:${usbIdToString(drive.deviceDescriptor.idProduct)}`,
- displayName: 'Missing drivers',
- description,
- mountpoints: [],
- isReadOnly: false,
- isSystem: false,
- disabled: true,
- icon: 'warning',
- size: null,
- link: 'https://www.raspberrypi.org/documentation/hardware/computemodule/cm-emmc-flashing.md',
- linkCTA: 'Install',
- linkTitle: 'Install missing drivers',
- linkMessage: [
- 'Would you like to download the necessary drivers from the Raspberry Pi Foundation?',
- 'This will open your browser.\n\n',
- 'Once opened, download and run the installer from the "Windows Installer" section to install the drivers.'
- ].join(' ')
- }
+// eslint-disable-next-line require-jsdoc,consistent-return
+const prepareDrive = (drive) => {
+ if (drive instanceof sdk.sourceDestination.BlockDevice) {
+ return drive.drive
+ } else if (drive instanceof sdk.sourceDestination.UsbbootDrive) {
+ // This is a workaround etcher expecting a device string and a size
+ drive.device = drive.usbDevice.portId
+ drive.size = null
+ drive.progress = 0
+ drive.disabled = true
+ drive.on('progress', (progress) => {
+ updateDriveProgress(drive, progress)
+ })
+ return drive
+ } else if (drive instanceof sdk.sourceDestination.DriverlessDevice) {
+ const description = COMPUTE_MODULE_DESCRIPTIONS[drive.deviceDescriptor.idProduct] || 'Compute Module'
+ return {
+ device: `${usbIdToString(drive.deviceDescriptor.idVendor)}:${usbIdToString(drive.deviceDescriptor.idProduct)}`,
+ displayName: 'Missing drivers',
+ description,
+ mountpoints: [],
+ isReadOnly: false,
+ isSystem: false,
+ disabled: true,
+ icon: 'warning',
+ size: null,
+ link: 'https://www.raspberrypi.org/documentation/hardware/computemodule/cm-emmc-flashing.md',
+ linkCTA: 'Install',
+ linkTitle: 'Install missing drivers',
+ linkMessage: [
+ 'Would you like to download the necessary drivers from the Raspberry Pi Foundation?',
+ 'This will open your browser.\n\n',
+ 'Once opened, download and run the installer from the "Windows Installer" section to install the drivers.'
+ ].join(' ')
}
}
+}
- // eslint-disable-next-line require-jsdoc
- const setDrives = (drives) => {
- availableDrives.setDrives(_.values(drives))
+// eslint-disable-next-line require-jsdoc
+const setDrives = (drives) => {
+ availableDrives.setDrives(_.values(drives))
+}
- // Safely trigger a digest cycle.
- // In some cases, AngularJS doesn't acknowledge that the
- // available drives list has changed, and incorrectly
- // keeps asking the user to "Connect a drive".
- $timeout()
+// eslint-disable-next-line require-jsdoc
+const getDrives = () => {
+ return _.keyBy(availableDrives.getDrives() || [], 'device')
+}
+
+// eslint-disable-next-line require-jsdoc
+const addDrive = (drive) => {
+ const preparedDrive = prepareDrive(drive)
+ if (!driveIsAllowed(preparedDrive)) {
+ return
}
+ const drives = getDrives()
+ drives[preparedDrive.device] = preparedDrive
+ setDrives(drives)
+}
- // eslint-disable-next-line require-jsdoc
- const getDrives = () => {
- return _.keyBy(availableDrives.getDrives() || [], 'device')
- }
+// eslint-disable-next-line require-jsdoc
+const removeDrive = (drive) => {
+ const preparedDrive = prepareDrive(drive)
+ const drives = getDrives()
+ // eslint-disable-next-line prefer-reflect
+ delete drives[preparedDrive.device]
+ setDrives(drives)
+}
- // eslint-disable-next-line require-jsdoc
- const addDrive = (drive) => {
- const preparedDrive = prepareDrive(drive)
- if (!driveIsAllowed(preparedDrive)) {
- return
- }
- const drives = getDrives()
- drives[preparedDrive.device] = preparedDrive
+// eslint-disable-next-line require-jsdoc
+const updateDriveProgress = (drive, progress) => {
+ const drives = getDrives()
+ const driveInMap = drives[drive.device]
+ if (driveInMap) {
+ driveInMap.progress = progress
setDrives(drives)
}
+}
- // eslint-disable-next-line require-jsdoc
- const removeDrive = (drive) => {
- const preparedDrive = prepareDrive(drive)
- const drives = getDrives()
- // eslint-disable-next-line prefer-reflect
- delete drives[preparedDrive.device]
- setDrives(drives)
- }
+driveScanner.on('attach', addDrive)
+driveScanner.on('detach', removeDrive)
- // eslint-disable-next-line require-jsdoc
- const updateDriveProgress = (drive, progress) => {
- const drives = getDrives()
- const driveInMap = drives[drive.device]
- if (driveInMap) {
- driveInMap.progress = progress
- setDrives(drives)
- }
- }
+driveScanner.on('error', (error) => {
+ // Stop the drive scanning loop in case of errors,
+ // otherwise we risk presenting the same error over
+ // and over again to the user, while also heavily
+ // spamming our error reporting service.
+ driveScanner.stop()
- driveScanner.on('attach', addDrive)
- driveScanner.on('detach', removeDrive)
-
- driveScanner.on('error', (error) => {
- // Stop the drive scanning loop in case of errors,
- // otherwise we risk presenting the same error over
- // and over again to the user, while also heavily
- // spamming our error reporting service.
- driveScanner.stop()
-
- return exceptionReporter.report(error)
- })
-
- driveScanner.start()
+ return exceptionReporter.report(error)
})
-app.run(($window) => {
- let popupExists = false
+driveScanner.start()
- $window.addEventListener('beforeunload', (event) => {
- if (!flashState.isFlashing() || popupExists) {
- analytics.logEvent('Close application', {
- isFlashing: flashState.isFlashing(),
- applicationSessionUuid
- })
- return
- }
+let popupExists = false
- // Don't close window while flashing
- event.returnValue = false
-
- // Don't open any more popups
- popupExists = true
-
- analytics.logEvent('Close attempt while flashing', { applicationSessionUuid, flashingWorkflowUuid })
-
- osDialog.showWarning({
- confirmationLabel: 'Yes, quit',
- rejectionLabel: 'Cancel',
- title: 'Are you sure you want to close Etcher?',
- description: messages.warning.exitWhileFlashing()
- }).then((confirmed) => {
- if (confirmed) {
- analytics.logEvent('Close confirmed while flashing', {
- flashInstanceUuid: flashState.getFlashUuid(),
- applicationSessionUuid,
- flashingWorkflowUuid
- })
-
- // This circumvents the 'beforeunload' event unlike
- // electron.remote.app.quit() which does not.
- electron.remote.process.exit(EXIT_CODES.SUCCESS)
- }
-
- analytics.logEvent('Close rejected while flashing', { applicationSessionUuid, flashingWorkflowUuid })
- popupExists = false
- }).catch(exceptionReporter.report)
- })
-
- /**
- * @summary Helper fn for events
- * @function
- * @private
- * @example
- * window.addEventListener('click', extendLock)
- */
- const extendLock = () => {
- updateLock.extend()
- }
-
- $window.addEventListener('click', extendLock)
- $window.addEventListener('touchstart', extendLock)
-
- // Initial update lock acquisition
- extendLock()
-})
-
-app.run(($rootScope) => {
- $rootScope.$on('$stateChangeSuccess', (event, toState, toParams, fromState) => {
- // Ignore first navigation
- if (!fromState.name) {
- return
- }
-
- analytics.logEvent('Navigate', {
- to: toState.name,
- from: fromState.name,
+window.addEventListener('beforeunload', (event) => {
+ if (!flashState.isFlashing() || popupExists) {
+ analytics.logEvent('Close application', {
+ isFlashing: flashState.isFlashing(),
applicationSessionUuid
})
- })
-})
+ return
+ }
-app.config(($urlRouterProvider) => {
- $urlRouterProvider.otherwise('/main')
-})
+ // Don't close window while flashing
+ event.returnValue = false
-app.config(($provide) => {
- $provide.decorator('$exceptionHandler', ($delegate) => {
- return (exception, cause) => {
- exceptionReporter.report(exception)
- $delegate(exception, cause)
+ // Don't open any more popups
+ popupExists = true
+
+ analytics.logEvent('Close attempt while flashing', { applicationSessionUuid, flashingWorkflowUuid })
+
+ osDialog.showWarning({
+ confirmationLabel: 'Yes, quit',
+ rejectionLabel: 'Cancel',
+ title: 'Are you sure you want to close Etcher?',
+ description: messages.warning.exitWhileFlashing()
+ }).then((confirmed) => {
+ if (confirmed) {
+ analytics.logEvent('Close confirmed while flashing', {
+ flashInstanceUuid: flashState.getFlashUuid(),
+ applicationSessionUuid,
+ flashingWorkflowUuid
+ })
+
+ // This circumvents the 'beforeunload' event unlike
+ // electron.remote.app.quit() which does not.
+ electron.remote.process.exit(EXIT_CODES.SUCCESS)
}
- })
-})
-app.config(($locationProvider) => {
- // NOTE(Shou): this seems to invoke a minor perf decrease when set to true
- $locationProvider.html5Mode({
- rewriteLinks: false
- })
-})
-
-app.controller('StateController', function ($rootScope, $scope) {
- const unregisterStateChange = $rootScope.$on('$stateChangeSuccess', (event, toState, toParams, fromState) => {
- this.currentName = toState.name
- })
-
- $scope.$on('$destroy', unregisterStateChange)
-
- /**
- * @summary Get the current state name
- * @function
- * @public
- *
- * @returns {String} current state name
- *
- * @example
- * if (StateController.currentName === 'main') {
- * console.log('We are on the main screen!');
- * }
- */
- this.currentName = null
-})
-
-// Ensure user settings are loaded before
-// we bootstrap the Angular.js application
-angular.element(document).ready(() => {
- settings.load().then(() => {
- angular.bootstrap(document, [ 'Etcher' ])
+ analytics.logEvent('Close rejected while flashing', { applicationSessionUuid, flashingWorkflowUuid })
+ popupExists = false
}).catch(exceptionReporter.report)
})
+
+/**
+ * @summary Helper fn for events
+ * @function
+ * @private
+ * @example
+ * window.addEventListener('click', extendLock)
+ */
+const extendLock = () => {
+ updateLock.extend()
+}
+
+window.addEventListener('click', extendLock)
+window.addEventListener('touchstart', extendLock)
+
+// Initial update lock acquisition
+extendLock()
+
+settings.load().catch(exceptionReporter.report)
+
+require('./tsapp.tsx')
diff --git a/lib/gui/app/components/finish/finish.tsx b/lib/gui/app/components/finish/finish.tsx
index e3d2a7e4..c76bc77a 100644
--- a/lib/gui/app/components/finish/finish.tsx
+++ b/lib/gui/app/components/finish/finish.tsx
@@ -29,7 +29,7 @@ import { FlashAnother } from '../flash-another/flash-another';
import { FlashResults } from '../flash-results/flash-results';
import * as SVGIcon from '../svg-icon/svg-icon';
-const restart = (options: any, $state: any) => {
+const restart = (options: any, goToMain: () => void) => {
const {
applicationSessionUuid,
flashingWorkflowUuid,
@@ -54,7 +54,7 @@ const restart = (options: any, $state: any) => {
data: uuidV4(),
});
- $state.go('main');
+ goToMain();
};
const formattedErrors = () => {
@@ -67,7 +67,7 @@ const formattedErrors = () => {
return errors.join('\n');
};
-function FinishPage({ $state }: any) {
+function FinishPage({ goToMain }: { goToMain: () => void }) {
// @ts-ignore
const results = flashState.getFlashResults().results || {};
const progressMessage = messages.progress;
@@ -82,7 +82,7 @@ function FinishPage({ $state }: any) {
>