mirror of
https://github.com/cryptomator/cryptomator.git
synced 2026-05-17 10:11:27 +00:00
show progress during vault migration (ugly prototype)
This commit is contained in:
@@ -7,8 +7,13 @@ import javafx.animation.Timeline;
|
||||
import javafx.beans.binding.Bindings;
|
||||
import javafx.beans.binding.ObjectBinding;
|
||||
import javafx.beans.property.BooleanProperty;
|
||||
import javafx.beans.property.DoubleProperty;
|
||||
import javafx.beans.property.ReadOnlyDoubleProperty;
|
||||
import javafx.beans.property.SimpleBooleanProperty;
|
||||
import javafx.beans.property.SimpleDoubleProperty;
|
||||
import javafx.beans.value.WritableValue;
|
||||
import javafx.concurrent.ScheduledService;
|
||||
import javafx.concurrent.Task;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.control.ContentDisplay;
|
||||
@@ -17,6 +22,7 @@ import javafx.util.Duration;
|
||||
import org.cryptomator.common.vaults.Vault;
|
||||
import org.cryptomator.common.vaults.VaultState;
|
||||
import org.cryptomator.cryptofs.migration.Migrators;
|
||||
import org.cryptomator.cryptofs.migration.api.MigrationProgressListener;
|
||||
import org.cryptomator.cryptofs.migration.api.NoApplicableMigratorException;
|
||||
import org.cryptomator.cryptolib.api.InvalidPassphraseException;
|
||||
import org.cryptomator.keychain.KeychainAccess;
|
||||
@@ -39,6 +45,7 @@ public class MigrationRunController implements FxController {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(MigrationRunController.class);
|
||||
private static final String MASTERKEY_FILENAME = "masterkey.cryptomator"; // TODO: deduplicate constant declared in multiple classes
|
||||
private static final Duration MIGRATION_PROGRESS_UPDATE_INTERVAL = Duration.millis(25);
|
||||
|
||||
private final Stage window;
|
||||
private final Vault vault;
|
||||
@@ -48,6 +55,9 @@ public class MigrationRunController implements FxController {
|
||||
private final Lazy<Scene> successScene;
|
||||
private final ObjectBinding<ContentDisplay> migrateButtonContentDisplay;
|
||||
private final BooleanProperty migrationButtonDisabled;
|
||||
private final DoubleProperty migrationProgress;
|
||||
private final ScheduledService<Double> migrationProgressObservationService;
|
||||
private volatile double volatileMigrationProgress = -1.0;
|
||||
public NiceSecurePasswordField passwordField;
|
||||
|
||||
@Inject
|
||||
@@ -60,6 +70,10 @@ public class MigrationRunController implements FxController {
|
||||
this.successScene = successScene;
|
||||
this.migrateButtonContentDisplay = Bindings.createObjectBinding(this::getMigrateButtonContentDisplay, vault.stateProperty());
|
||||
this.migrationButtonDisabled = new SimpleBooleanProperty();
|
||||
this.migrationProgress = new SimpleDoubleProperty(volatileMigrationProgress);
|
||||
this.migrationProgressObservationService = new MigrationProgressObservationService();
|
||||
migrationProgressObservationService.setExecutor(executor);
|
||||
migrationProgressObservationService.setPeriod(MIGRATION_PROGRESS_UPDATE_INTERVAL);
|
||||
}
|
||||
|
||||
public void initialize() {
|
||||
@@ -79,17 +93,18 @@ public class MigrationRunController implements FxController {
|
||||
LOG.info("Migrating vault {}", vault.getPath());
|
||||
CharSequence password = passwordField.getCharacters();
|
||||
vault.setState(VaultState.PROCESSING);
|
||||
migrationProgressObservationService.start();
|
||||
Tasks.create(() -> {
|
||||
Migrators migrators = Migrators.get();
|
||||
migrators.migrate(vault.getPath(), MASTERKEY_FILENAME, password);
|
||||
migrators.migrate(vault.getPath(), MASTERKEY_FILENAME, password, this::migrationProgressChanged);
|
||||
return migrators.needsMigration(vault.getPath(), MASTERKEY_FILENAME);
|
||||
}).onSuccess(needsAnotherMigration -> {
|
||||
LOG.info("Migration of '{}' succeeded.", vault.getDisplayableName());
|
||||
if (needsAnotherMigration) {
|
||||
vault.setState(VaultState.NEEDS_MIGRATION);
|
||||
} else {
|
||||
vault.setState(VaultState.LOCKED);
|
||||
passwordField.swipe();
|
||||
LOG.info("Migration of '{}' succeeded.", vault.getDisplayableName());
|
||||
window.setScene(successScene.get());
|
||||
}
|
||||
}).onError(InvalidPassphraseException.class, e -> {
|
||||
@@ -105,9 +120,29 @@ public class MigrationRunController implements FxController {
|
||||
LOG.error("Migration failed for technical reasons.", e);
|
||||
vault.setState(VaultState.ERROR);
|
||||
// TODO show generic error screen
|
||||
}).andFinally(() -> {
|
||||
migrationProgressObservationService.cancel();
|
||||
migrationProgressObservationService.reset();
|
||||
}).runOnce(executor);
|
||||
}
|
||||
|
||||
// Called by a background task. We can not directly modify observable properties from here
|
||||
private void migrationProgressChanged(MigrationProgressListener.ProgressState state, double progress) {
|
||||
switch (state) {
|
||||
case INITIALIZING:
|
||||
volatileMigrationProgress = -1.0;
|
||||
break;
|
||||
case MIGRATING:
|
||||
volatileMigrationProgress = progress;
|
||||
break;
|
||||
case FINALIZING:
|
||||
volatileMigrationProgress = 1.0;
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Unexpted state " + state);
|
||||
}
|
||||
}
|
||||
|
||||
private void loadStoredPassword() {
|
||||
assert keychainAccess.isPresent();
|
||||
char[] storedPw = null;
|
||||
@@ -126,6 +161,27 @@ public class MigrationRunController implements FxController {
|
||||
}
|
||||
}
|
||||
|
||||
// Sets migrationProgress to volatileMigrationProgress at its configured interval
|
||||
private class MigrationProgressObservationService extends ScheduledService<Double> {
|
||||
|
||||
@Override
|
||||
protected Task<Double> createTask() {
|
||||
return new Task<>() {
|
||||
@Override
|
||||
protected Double call() {
|
||||
return volatileMigrationProgress;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void succeeded() {
|
||||
assert getValue() != null;
|
||||
migrationProgress.set(getValue());
|
||||
super.succeeded();
|
||||
}
|
||||
}
|
||||
|
||||
/* Animations */
|
||||
|
||||
private void shakeWindow() {
|
||||
@@ -180,4 +236,12 @@ public class MigrationRunController implements FxController {
|
||||
}
|
||||
}
|
||||
|
||||
public ReadOnlyDoubleProperty migrationProgressProperty() {
|
||||
return migrationProgress;
|
||||
}
|
||||
|
||||
public double getMigrationProgress() {
|
||||
return migrationProgress.get();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,6 +23,9 @@
|
||||
<NiceSecurePasswordField fx:id="passwordField"/>
|
||||
</VBox>
|
||||
|
||||
<!-- TODO add a progress bar... -->
|
||||
<FormattedLabel format="progress: %.3f" arg1="${controller.migrationProgress}"/>
|
||||
|
||||
<VBox alignment="BOTTOM_CENTER" VBox.vgrow="ALWAYS">
|
||||
<ButtonBar buttonMinWidth="120" buttonOrder="B+X">
|
||||
<buttons>
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
<?import javafx.scene.control.Button?>
|
||||
<?import javafx.scene.layout.VBox?>
|
||||
<?import org.cryptomator.ui.controls.FontAwesome5IconView?>
|
||||
<?import javafx.scene.control.Label?>
|
||||
<VBox xmlns="http://javafx.com/javafx"
|
||||
xmlns:fx="http://javafx.com/fxml"
|
||||
fx:controller="org.cryptomator.ui.mainwindow.VaultDetailNeedsMigrationController"
|
||||
@@ -12,9 +11,7 @@
|
||||
<Insets topRightBottomLeft="24"/>
|
||||
</padding>
|
||||
<children>
|
||||
<!-- TODO -->
|
||||
<Label text="Migration disabled during Alpha"/>
|
||||
<Button styleClass="button-large" text="TODO Upgrade Vault" minWidth="120" onAction="#showVaultMigrator" disable="true">
|
||||
<Button styleClass="button-large" text="TODO Upgrade Vault" minWidth="120" onAction="#showVaultMigrator">
|
||||
<graphic>
|
||||
<FontAwesome5IconView glyph="FILE_IMPORT" glyphSize="15"/>
|
||||
</graphic>
|
||||
|
||||
Reference in New Issue
Block a user