diff --git a/build/css/main.css b/build/css/main.css index fb34f6b5..0d7166b0 100644 --- a/build/css/main.css +++ b/build/css/main.css @@ -1250,7 +1250,7 @@ mark, .text-left { text-align: left; } -.text-right { +.text-right, .section-header { text-align: right; } .text-center { @@ -5854,23 +5854,13 @@ button.close { margin-top: 15px; margin-bottom: 15px; } -.space-top-huge { - margin-top: 45px; } - .space-vertical-large { margin-top: 30px; margin-bottom: 30px; } -.space-horizontal-large { - margin-left: 30px; - margin-right: 30px; } - .space-bottom-large { margin-bottom: 30px; } -.space-bottom-huge { - margin-bottom: 45px; } - .space-right-tiny { margin-right: 5px; } @@ -5981,8 +5971,13 @@ body { .checkbox input[type="checkbox"]:not(:checked) + * { color: #ddd; } -.btn-navigation { - position: fixed; - top: 10px; - right: 10px; +.wrapper { + height: 100%; + margin: 20px 60px; } + +h1, h2, h3, h4, h5, h6 { + margin-top: 0; } + +.section-header { + padding: 5px; font-size: 15px; } diff --git a/lib/browser/app.js b/lib/browser/app.js index bba96930..1f942417 100644 --- a/lib/browser/app.js +++ b/lib/browser/app.js @@ -29,6 +29,7 @@ const BrowserWindow = electron.remote.BrowserWindow; const currentWindow = BrowserWindow.fromId(1); require('angular-ui-bootstrap'); +require('angular-ui-router'); require('./browser/modules/selection-state'); require('./browser/modules/settings'); require('./browser/modules/drive-scanner'); @@ -37,6 +38,7 @@ require('./browser/modules/path'); require('./browser/modules/analytics'); const app = angular.module('Etcher', [ + 'ui.router', 'ui.bootstrap', // Etcher modules @@ -48,55 +50,71 @@ const app = angular.module('Etcher', [ 'Etcher.analytics' ]); +app.config(function($stateProvider, $urlRouterProvider) { + $urlRouterProvider.otherwise('/main'); + + $stateProvider + .state('main', { + url: '/main', + controller: 'AppController as app', + templateUrl: './partials/main.html' + }) + .state('success', { + url: '/success', + controller: 'FinishController as finish', + templateUrl: './partials/success.html' + }) + .state('settings', { + url: '/settings', + controller: 'SettingsController as settings', + templateUrl: './partials/settings.html' + }); +}); + app.controller('AppController', function( $q, + $state, DriveScannerService, - SettingsService, SelectionStateService, ImageWriterService, AnalyticsService ) { let self = this; - this.settings = SettingsService; this.selection = SelectionStateService; this.writer = ImageWriterService; this.scanner = DriveScannerService; - this.restart = function(options) { - AnalyticsService.logEvent('Restart'); - this.selection.clear(options); + AnalyticsService.logEvent('Restart'); - self.state = { + if (!this.writer.isBurning()) { + this.state = { progress: 0, percentage: 0 }; + } - this.scanner.start(2000).on('scan', function(drives) { + this.scanner.start(2000).on('scan', function(drives) { - // Notice we only autoselect the drive if there is an image, - // which means that the first step was completed successfully, - // otherwise the drive is selected while the drive step is disabled - // which looks very weird. - if (drives.length === 1 && self.selection.hasImage()) { - const drive = _.first(drives); - - // Do not autoselect the same drive over and over again - // and fill the logs unnecessary. - // `angular.equals` is used instead of `_.isEqual` to - // cope with `$$hashKey`. - if (!angular.equals(self.selection.getDrive(), drive)) { - AnalyticsService.logEvent('Auto-select drive', { - device: drive.device - }); - self.selectDrive(drive); - } + // Notice we only autoselect the drive if there is an image, + // which means that the first step was completed successfully, + // otherwise the drive is selected while the drive step is disabled + // which looks very weird. + if (drives.length === 1 && self.selection.hasImage()) { + const drive = _.first(drives); + // Do not autoselect the same drive over and over again + // and fill the logs unnecessary. + // `angular.equals` is used instead of `_.isEqual` to + // cope with `$$hashKey`. + if (!angular.equals(self.selection.getDrive(), drive)) { + AnalyticsService.logEvent('Auto-select drive', { + device: drive.device + }); + self.selectDrive(drive); } - }); - }; - - this.restart(); + } + }); // We manually add `style="display: none;"` to // and unset it here instead of using ngCloak since @@ -167,6 +185,7 @@ app.controller('AppController', function( }).then(function() { AnalyticsService.logEvent('Done'); + $state.go('success'); }).catch(dialog.showError).finally(function() { // Remove progress bar from task bar @@ -179,3 +198,18 @@ app.controller('AppController', function( this.open = shell.openExternal; }); + +app.controller('SettingsController', function(SettingsService) { + this.storage = SettingsService.data; +}); + +app.controller('NavigationController', function($state) { + this.isState = $state.is; +}); + +app.controller('FinishController', function($state, SelectionStateService) { + this.restart = function(options) { + SelectionStateService.clear(options); + $state.go('main'); + }; +}); diff --git a/lib/browser/modules/settings.js b/lib/browser/modules/settings.js index 25372dd1..4089b997 100644 --- a/lib/browser/modules/settings.js +++ b/lib/browser/modules/settings.js @@ -38,57 +38,4 @@ settings.service('SettingsService', function($localStorage) { errorReporting: true }); - // All this functionality should be gone once - // we make use of a real router on the application. - // This is not the case yet since when the application - // was first prototyped there was only one screen - // and therefore a router would have been overkill. - - /** - * @summary Configuring state - * @type Boolean - * @private - */ - let configuring = false; - - /** - * @summary Check if the user is configuring - * @function - * @public - * - * @returns {Boolean} whether is configuring - * - * @example - * if (SettingsService.isConfiguring()) { - * console.log('User is on settings screen'); - * } - */ - this.isConfiguring = function() { - return configuring; - }; - - /** - * @summary Enter settings screen - * @function - * @public - * - * @example - * SettingsService.enter(); - */ - this.enter = function() { - configuring = true; - }; - - /** - * @summary Leave settings screen - * @function - * @public - * - * @example - * SettingsService.leave(); - */ - this.leave = function() { - configuring = false; - }; - }); diff --git a/lib/css/desktop.css b/lib/css/desktop.css index 2c77c9cb..c3fd0bd4 100644 --- a/lib/css/desktop.css +++ b/lib/css/desktop.css @@ -35,6 +35,8 @@ body { -webkit-overflow-scrolling: touch; } +/* Prevent blue outline */ +input:focus, button:focus { outline: none !important; } diff --git a/lib/index.html b/lib/index.html index f12a2618..63ad39fe 100644 --- a/lib/index.html +++ b/lib/index.html @@ -24,142 +24,20 @@ - -
- -
-
-
-
- - 1 + + -
-
- Select image - -
-
- -
-
-
-
+
-
-
-
-
- - - 2 - -
-
- -
-
- Select drive - - -
-
- -
- Connect a drive -
- -
-
-
-
-
- -
-
- - 3 - -
- - Finishing... - Burn! - Starting... - - - - -
-
-
-
- -
-
-
-

Burn Complete!

-

Safely ejected and ready for use

- -
-
-
-

Would you like to burn the same image?

- - - Use same image - -
-
- -
- -
-
-

Would you like to burn a new image?

- - - Use new image - -
-
-
-
-
-
-
-
- -
-
- - -
-

Settings

- -
- -
-
-
-
- - + diff --git a/lib/partials/main.html b/lib/partials/main.html new file mode 100644 index 00000000..1c49c21c --- /dev/null +++ b/lib/partials/main.html @@ -0,0 +1,73 @@ +
+
+
+ + 1 + +
+
+ Select image + +
+
+ +
+
+
+
+ +
+
+
+
+ + + 2 + +
+
+ +
+
+ Select drive + + +
+
+ +
+ Connect a drive +
+ +
+
+
+
+
+ +
+
+ + 3 + +
+ + Finishing... + Burn! + Starting... + + + + +
+
+
+
diff --git a/lib/partials/settings.html b/lib/partials/settings.html new file mode 100644 index 00000000..9c9c0d1f --- /dev/null +++ b/lib/partials/settings.html @@ -0,0 +1,10 @@ +
+

Settings

+ +
+ +
+
diff --git a/lib/partials/success.html b/lib/partials/success.html new file mode 100644 index 00000000..51dd90d3 --- /dev/null +++ b/lib/partials/success.html @@ -0,0 +1,32 @@ +
+
+
+

Burn Complete!

+

Safely ejected and ready for use

+ +
+
+
+

Would you like to burn the same image?

+ + + Use same image + +
+
+ +
+ +
+
+

Would you like to burn a new image?

+ + + Use new image + +
+
+
+
+
+
diff --git a/lib/scss/main.scss b/lib/scss/main.scss index e4cfc947..4a4f5950 100644 --- a/lib/scss/main.scss +++ b/lib/scss/main.scss @@ -184,9 +184,17 @@ body { color: $gray-light; } -.btn-navigation { - position: fixed; - top: 10px; - right: 10px; +.wrapper { + height: 100%; + margin: 20px 60px; +} + +h1, h2, h3, h4, h5, h6 { + margin-top: 0; +} + +.section-header { + @extend .text-right; + padding: 5px; font-size: 15px; } diff --git a/lib/scss/modules/_space.scss b/lib/scss/modules/_space.scss index 4fb3b207..edd426c7 100644 --- a/lib/scss/modules/_space.scss +++ b/lib/scss/modules/_space.scss @@ -14,7 +14,6 @@ * limitations under the License. */ -$spacing-huge: 45px; $spacing-large: 30px; $spacing-medium: 15px; $spacing-tiny: 5px; @@ -28,28 +27,15 @@ $spacing-tiny: 5px; margin-bottom: $spacing-medium; } -.space-top-huge { - margin-top: $spacing-huge; -} - .space-vertical-large { margin-top: $spacing-large; margin-bottom: $spacing-large; } -.space-horizontal-large { - margin-left: $spacing-large; - margin-right: $spacing-large; -} - .space-bottom-large { margin-bottom: $spacing-large; } -.space-bottom-huge { - margin-bottom: $spacing-huge; -} - .space-right-tiny { margin-right: $spacing-tiny; } diff --git a/package.json b/package.json index c676673f..11317e5f 100644 --- a/package.json +++ b/package.json @@ -52,6 +52,7 @@ "dependencies": { "angular": "^1.4.6", "angular-ui-bootstrap": "^1.2.1", + "angular-ui-router": "^0.2.18", "bluebird": "^3.0.5", "bootstrap-sass": "^3.3.5", "drivelist": "^2.0.7", diff --git a/tests/browser/modules/settings.spec.js b/tests/browser/modules/settings.spec.js deleted file mode 100644 index cdca9bb2..00000000 --- a/tests/browser/modules/settings.spec.js +++ /dev/null @@ -1,51 +0,0 @@ -'use strict'; - -const m = require('mochainon'); -const angular = require('angular'); -require('angular-mocks'); -require('../../../lib/browser/modules/settings'); - -describe('Browser: Settings', function() { - - beforeEach(angular.mock.module('Etcher.settings')); - - describe('SettingsService', function() { - - let SettingsService; - - beforeEach(angular.mock.inject(function(_SettingsService_) { - SettingsService = _SettingsService_; - })); - - describe('.isConfiguring()', function() { - - it('should initially return false', function() { - m.chai.expect(SettingsService.isConfiguring()).to.be.false; - }); - - }); - - describe('.enter()', function() { - - it('should be able to enter settings', function() { - m.chai.expect(SettingsService.isConfiguring()).to.be.false; - SettingsService.enter(); - m.chai.expect(SettingsService.isConfiguring()).to.be.true; - }); - - }); - - describe('.leave()', function() { - - it('should be able to leave settings', function() { - SettingsService.enter(); - m.chai.expect(SettingsService.isConfiguring()).to.be.true; - SettingsService.leave(); - m.chai.expect(SettingsService.isConfiguring()).to.be.false; - }); - - }); - - }); - -});