30 Commits

Author SHA1 Message Date
Juan Cruz Viotti
1a49b36a14 refactor: store settings in redux store (#530)
* refactor: getter/setter interface for SettingsModel

This PR introduces a getter/setter interface for `SettingsModel`, which
replaces the old way of managing setting values by simply assigning
properties to an object.

This is the first step towards moving the settings functionality to the
Redux store.

Signed-off-by: Juan Cruz Viotti <jviottidc@gmail.com>

* refactor: store settings in redux store

The state data structure now contains a property called `settings`,
which is a map containing all setting values.

The list of supported settings can be calculated by retrieving the keys
from the `settings` object, which means that if we support a setting, we
must include a default.

Signed-off-by: Juan Cruz Viotti <jviottidc@gmail.com>

* feat: store settings in localStorage

This functionality was deleted by acb0de2 when moving the settings
object to the redux store, promising that the feature will be added back
in a future commit.

Signed-off-by: Juan Cruz Viotti <jviottidc@gmail.com>
2016-06-24 16:06:27 -04:00
Juan Cruz Viotti
714b165c0c refactor: move flash results state to Redux store (#529)
This is a rather big PR that moves the flash results information to the
Redux store, which simplifies and improves a lot of things as throughly
described in the commits that introduced Redux.

Here's a summary of the changes:

- Add a `flashResults` property to the store.

- Validate the contents of `flashResults`, handling certain edge cases
that make the modal incoherent.

- Split `ImageWriterService.setFlashing()` to
`ImageWriterService.setFlashingFlag()` and
`ImageWriterService.unsetFlashingFlag()`.

- Require the flash results to be passed to
`ImageWriterService.unsetFlashingFlag()`.

- Stop resolving the flash results from `ImageWriterService.flash()`.

- Implement `ImageWriterService.getFlashResults()`.

- Make the `RESET_FLASH_STATE` action reset the flash results.

- Access the source checksum from the store in the "finish" page,
  instead of requiring the controller to pass it as a state parameter.

- Implement `.wasLastFlashSuccessful()` function in the main controller
to replace the `.success` property.

- Completely remove the `.success` property in the main controller.

Signed-off-by: Juan Cruz Viotti <jviottidc@gmail.com>
2016-06-24 12:52:40 -04:00
Juan Cruz Viotti
60b68d775b refactor: rename progress property to percentage (#527)
So the property is consistent from what we get from `etcher-image-write`
and we don't have to unnecessarily rename ourselves to pass it to the
model.

Signed-off-by: Juan Cruz Viotti <jviottidc@gmail.com>
2016-06-24 09:47:10 -04:00
Juan Cruz Viotti
c291a9067d fix: emit progress even when not in the main screen (#523)
We have logic that displays useful log messages about the state of the
flashing, as well as update the window progress in each oeprating system
(dock in OS X, task bar in Windows, etc), however since this logic lives
in the controller, the progress reports are completely frozen if the
user navigates away from the main screen (to the settings page for
example).

As a solution, we move the code that subscribes to the state change
events to a global `.run()` so it can persist page changes.

Since making sure the listeners are unregistered is not relevant anymore
(since the code is not running in a controller anymore), we get rid of
`NotifierService`, a module we built for this purpose, and directly
subscribe to the Redux store instead.

Signed-off-by: Juan Cruz Viotti <jviottidc@gmail.com>
2016-06-23 18:39:15 -04:00
Juan Cruz Viotti
c44594b45e refactor: use ES6 fat arrows in application code (#522)
ES6 fat arrows provide reasonable `this` behaviour, which protects us
from some subtle accidental bugs, and erradicates `const self = this`
from the codebase.

Far arrows were not applied in Mocha code and AngularJS
controllers/services constructors since these frameworks rely on
`.bind()` on those functions.

Signed-off-by: Juan Cruz Viotti <jviottidc@gmail.com>
2016-06-23 17:41:41 -04:00
Juan Cruz Viotti
2ecf9d32a7 refactor: reset state when the flashing flag is set to false (#518)
Currently, we were taking care of resetting the flashing state manually
across several controllers. Now that data mutations live in a single
place, we trigger a flash state reset whenever the flashing flag is set
to false, which reliably handles every case and allows us to forget
about it.

Signed-off-by: Juan Cruz Viotti <jviottidc@gmail.com>
2016-06-23 15:12:57 -04:00
Juan Cruz Viotti
c845fe10b0 fix: check for updates only once at startup (#517)
Currently, the update check runs every single time the main application
controller is instantiated, meaning that the update check would run
again when you visit the settings screen and go back to the main page,
or return to the main page after finishing a flash.

Signed-off-by: Juan Cruz Viotti <jviottidc@gmail.com>
2016-06-23 12:19:32 -04:00
Juan Cruz Viotti
321c653d74 refactor: move auto-select logic to redux store (#516)
Now that we have a central source of truth for state mutations, the
auto-select feature fits really well in the redux store, particularly
inside the `SET_AVAILABLE_DRIVES` action.

This also has the great benefit that we can unit test the auto-selection
logic, which was not particularly trivial before, when such code lived
in the controller instead.

The only downside of this approach is that we lose the nice "Auto-select
drive" analytics event, which will be re-added very soon in a future PR.

Signed-off-by: Juan Cruz Viotti <jviottidc@gmail.com>
2016-06-23 12:19:27 -04:00
Juan Cruz Viotti
c2c5eb59b9 fix: deselect drive if its not available anymore (#513)
If the user has a selected drive, but a new scan shows that such drive
is no longer available, then the selected drive should be de-selected.

Signed-off-by: Juan Cruz Viotti <jviottidc@gmail.com>
2016-06-23 09:26:35 -04:00
Juan Cruz Viotti
991b69c17e refactor(DriveScannerService): use RxJS (#505)
The concept of a drive scanner lends itself very well to the concept of
"reactive programming", since the "available drives" make perfect sense
as an "Observable".

For this reason, the module was re-implemented using RxJS, which greatly
simplifies things and erradicates certain edge cases we were protecting
ourselves from automatically.

Other changes made in this PR:

- `DriveScannerService` no longer requires `DrivesModel`. The
`DriveScannerService` is the one in charge of populating the model.

- `DriveScannerService.scan()` no longer returns an `EventEmitter`. The
service itself is now an `EventEmitter`.

- `DriveScannerService` now emits a `drives`, not a `scan` event.

Signed-off-by: Juan Cruz Viotti <jviottidc@gmail.com>
2016-06-22 10:41:36 -04:00
Juan Cruz Viotti
b923008f7c refactor: make use of angular-if-state (#506)
We'll use this external module rather than our local `if-state`
implementation.

Signed-off-by: Juan Cruz Viotti <jviottidc@gmail.com>
2016-06-22 10:41:02 -04:00
Juan Cruz Viotti
95deab0b0d Get rid of application-wide elevation (#423)
Signed-off-by: Juan Cruz Viotti <jviottidc@gmail.com>
2016-06-20 21:49:16 -04:00
Juan Cruz Viotti
16c3750b15 Don't check extensions before the first non compressed extension (#493)
Currently, we extract all the extensions from an image path and report
back that the image is invalid if *any* of the extensions is not a
valida extension, however this can cause trouble with images including
information between dots that are not strictly extensions.

For example:

```
elementaryos-0.3.2-stable-i386.20151209.iso
```

Etcher will consider `20151209` to be an invalid extension and therefore
will prevent such image from being selected.

As a way to allow these corner cases but will make use of our enforced
check controls, the validation routine will only consider extensions
starting from the first non compressed extension.

This PR also includes logic to show a nice GUI dialog saying that the
image is invalid in order to provide a much better experience than just
silently failing.

Fixes: https://github.com/resin-io/etcher/issues/492
Signed-off-by: Juan Cruz Viotti <jviottidc@gmail.com>
2016-06-20 12:05:33 -04:00
Juan Cruz Viotti
21b6e1aabc Prevent an invalid drive from being auto-selected (#484)
Currently we have logic in the drive selector dialog to prevent invalid
drives (too small, locked, etc) from being selected, however we are not
protecting auto-selection from these invalid devices.

Signed-off-by: Juan Cruz Viotti <jviottidc@gmail.com>
2016-06-15 11:26:03 -04:00
Juan Cruz Viotti
8aa7bcd952 Prevent a very long image name from breaking the UI (#479)
This PR introduces two changes to mitigate this problem and overall
provide a better UX:

- Show ellipses in the middle of the image name in the first step if
needed.

- Add a tooltip below the image selection label in the first step to
show a little modal displaying the full path to the image.

Fixes: https://github.com/resin-io/etcher/issues/418
Signed-off-by: Juan Cruz Viotti <jviottidc@gmail.com>
2016-06-15 10:31:07 -04:00
Juan Cruz Viotti
34ab982b24 Remove body display hidden white flash workaround (#478)
In older versions of Electron, the application would display a quick
flash of white before running caused by the WebView loading up.

This workaround doesn't seem necessary anymore.

Signed-off-by: Juan Cruz Viotti <jviottidc@gmail.com>
2016-06-13 10:58:01 -04:00
Juan Cruz Viotti
5ae5a1915d Refactor supported image logic to SupportedFormatsModel (#467)
Signed-off-by: Juan Cruz Viotti <jviottidc@gmail.com>
2016-06-09 13:08:01 -04:00
Juan Cruz Viotti
b950136deb Extract DrivesModel from DriveScannerService (#466)
Currently, `DriveScannerService` is in charge of both scanning the
available drives and maintaining the state of the currently detected
drives.

To honour the single responsibility principle, we split this service
into a `DrivesModel`, which is incharge of maintaining the state without
caring how they are detected, and `DriveScannerService`, which only
scans the available drives and modified `DrivesModel` accordingly.

Signed-off-by: Juan Cruz Viotti <jviottidc@gmail.com>
2016-06-09 12:42:09 -04:00
Juan Cruz Viotti
fc6ccf70dd Prevent selection of invalid images (#462)
The user might attempt to select an invalid image by dropping on the
first step, which would cause Etcher to blindly select it, possibly
causing errors later on the process.

This PR makes use of the list of supported extensions provided by
`SupportedFormatsModel` and prevents the selection if necessary, logging
an event that might help us determine which unsupported image types
users try to burn most often.

Signed-off-by: Juan Cruz Viotti <jviottidc@gmail.com>
2016-06-08 15:49:55 -04:00
Juan Cruz Viotti
8de4be1897 Display ETA during flash and check (#460)
* Show speed during check

Signed-off-by: Juan Cruz Viotti <jviottidc@gmail.com>

* Display ETA during flash and check

Fixes: https://github.com/resin-io/etcher/issues/256
Signed-off-by: Juan Cruz Viotti <jviottidc@gmail.com>
2016-06-08 13:35:44 -04:00
Juan Cruz Viotti
abb7dc6469 Prevent pressing "space" to re-click the "Flash" button (#435)
Currently we disable pointer events on the "Flash" button once a flash
is in progress to prevent the user from clicking it, but we didn't
consider that if the user kept focus on the button, he can press the
"space" bar for the same effect.

Fixes: https://github.com/resin-io/etcher/issues/431
Signed-off-by: Juan Cruz Viotti <jviottidc@gmail.com>
2016-05-24 14:21:31 -04:00
Juan Cruz Viotti
3b30748b1f Add support for .gz and .bz2 (#419)
See: https://github.com/resin-io/etcher/issues/325
Signed-off-by: Juan Cruz Viotti <jviottidc@gmail.com>
2016-05-24 10:38:12 -04:00
Juan Cruz Viotti
e1a3c88b10 Display image checksum on success in the CLI (#417)
* Upgrade etcher-image-write to v5.0.0

Signed-off-by: Juan Cruz Viotti <jviottidc@gmail.com>

* Display image CRC32 checksum on success

Fixes: http://github.com/resin-io/etcher/issues/357
Signed-off-by: Juan Cruz Viotti <jviottidc@gmail.com>
2016-05-19 10:13:10 -04:00
Juan Cruz Viotti
bf37ee72df Prevent selection of drives that are not large enough (#408)
* Make .selectImage() dialog return an object with a `path` property

This allows to return more than one value for the selected image,
like image size and other metadata for example.

Signed-off-by: Juan Cruz Viotti <jviottidc@gmail.com>

* Return image size from .selectImage() dialog

This property will be useful to perform some sanity checks, like
ensuring the selected drive is large enough to contain the image.

Signed-off-by: Juan Cruz Viotti <jviottidc@gmail.com>

* Store both the image path and the image size in the selection model

In order to simplify accessing such properties in an encapsulated
manner, `SelectionStateModel.getImage()` was replaced with the following
functions:

- `SelectionStateModel.getImagePath()`.
- `SelectionStateModel.getImageSize()`.

Signed-off-by: Juan Cruz Viotti <jviottidc@gmail.com>

* Increase SelectionStateModel setter validation

The model not providing any kind of validation was the source of some
bugs I encountered while implementing the previous commits that would
not have happened otherwise.

Signed-off-by: Juan Cruz Viotti <jviottidc@gmail.com>

* Prevent selection of drives that are not large enough

- The drive selector modal was modified such that drives that are not
large enough are crossed out, and the user is not able to click them.

- In the case of drive auto-selection, not large enough drives won't
attempt to get autoselected.

This commit introduces:

- The `SelectionStateModel.isDriveLargeEnough()` function.

Fixes: https://github.com/resin-io/etcher/issues/344
Signed-off-by: Juan Cruz Viotti <jviottidc@gmail.com>
2016-05-12 15:38:19 -04:00
Juan Cruz Viotti
a4e2639c00 Implement update notifier modal (#406)
Auto-update functionality is not ready for usage. As a workaround to
prevent users staying with older versions, we now check for updates at
startup, and if the user is not running the latest version, we present a
modal informing the user of the availiblity of a new version, and
provide a call to action to open the Etcher website in his web browser.

Extra features:

- The user can skip the update, and tell the program to delay the
notification for 7 days.

Misc changes:

- Center modal with flexbox, to allow more flexibility on the modal height.
interacting with the S3 server.
- Implement `ManifestBindService`, which now serves as a backend for the
`manifest-bind` directive to allow the directive's functionality to be
re-used by other services.
- Namespace checkbox styles that are specific to the settings page.

Fixes: https://github.com/resin-io/etcher/issues/396
Signed-off-by: Juan Cruz Viotti <jviottidc@gmail.com>
2016-05-12 13:11:30 -04:00
Juan Cruz Viotti
369e38b310 Improve "Select Image" supported file types label with a tooltip (#392)
Fixes: https://github.com/resin-io/etcher/issues/378
Signed-off-by: Juan Cruz Viotti <jviottidc@gmail.com>
2016-05-04 01:30:54 -04:00
Juan Cruz Viotti
ad758cf391 Implement Etcher.OS.Dialog module (#381)
Signed-off-by: Juan Cruz Viotti <jviottidc@gmail.com>
2016-04-29 09:03:20 -04:00
Juan Cruz Viotti
4a856d24df Add entry point file to decide between GUI/CLI (#365)
This file runs the Etcher CLI if the binary was ran with
`ELECTRON_RUN_AS_NODE`, or the GUI otherwise.

Signed-off-by: Juan Cruz Viotti <jviottidc@gmail.com>
2016-04-26 11:39:15 -04:00
Juan Cruz Viotti
d5b3e0a83f Upgrade drivelist to v3.0.0 (#354)
This new version reports the size as a number of bytes instead of a
human readable string, so we have to take care of converting back to a
readable GB format ourselves.

Signed-off-by: Juan Cruz Viotti <jviottidc@gmail.com>
2016-04-25 12:46:59 -04:00
Juan Cruz Viotti
afeba11424 Move GUI code into lib/gui (#358)
This refactoring will be useful on future changes, where there will be
a single application entry point that will execute the CLI or the GUI
version depending on the environment.

Signed-off-by: Juan Cruz Viotti <jviottidc@gmail.com>
2016-04-25 12:08:19 -04:00