diff --git a/main/ui/src/main/java/org/cryptomator/ui/common/FxmlFile.java b/main/ui/src/main/java/org/cryptomator/ui/common/FxmlFile.java index cae0c9209..ae2f1ab45 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/common/FxmlFile.java +++ b/main/ui/src/main/java/org/cryptomator/ui/common/FxmlFile.java @@ -12,6 +12,7 @@ public enum FxmlFile { CHANGEPASSWORD("/fxml/changepassword.fxml"), // FORGET_PASSWORD("/fxml/forget_password.fxml"), // MAIN_WINDOW("/fxml/main_window.fxml"), // + MIGRATION_CAPABILITY_ERROR("/fxml/migration_capability_error.fxml"), // MIGRATION_GENERIC_ERROR("/fxml/migration_generic_error.fxml"), // MIGRATION_RUN("/fxml/migration_run.fxml"), // MIGRATION_START("/fxml/migration_start.fxml"), // diff --git a/main/ui/src/main/java/org/cryptomator/ui/migration/MigrationCapabilityErrorController.java b/main/ui/src/main/java/org/cryptomator/ui/migration/MigrationCapabilityErrorController.java new file mode 100644 index 000000000..e6c31b7a0 --- /dev/null +++ b/main/ui/src/main/java/org/cryptomator/ui/migration/MigrationCapabilityErrorController.java @@ -0,0 +1,57 @@ +package org.cryptomator.ui.migration; + +import dagger.Lazy; +import javafx.beans.binding.Bindings; +import javafx.beans.binding.StringBinding; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.ReadOnlyObjectProperty; +import javafx.fxml.FXML; +import javafx.scene.Scene; +import javafx.stage.Stage; +import org.cryptomator.cryptofs.common.FileSystemCapabilityChecker; +import org.cryptomator.ui.common.FxController; +import org.cryptomator.ui.common.FxmlFile; +import org.cryptomator.ui.common.FxmlScene; + +import javax.inject.Inject; +import javax.inject.Named; +import java.util.ResourceBundle; + +@MigrationScoped +public class MigrationCapabilityErrorController implements FxController { + + private final Stage window; + private final ResourceBundle localization; + private final Lazy startScene; + private final StringBinding missingCapabilityDescription; + private final ReadOnlyObjectProperty missingCapability; + + @Inject + MigrationCapabilityErrorController(@MigrationWindow Stage window, @Named("capabilityErrorCause") ObjectProperty missingCapability, ResourceBundle localization, @FxmlScene(FxmlFile.MIGRATION_START) Lazy startScene) { + this.window = window; + this.missingCapability = missingCapability; + this.localization = localization; + this.startScene = startScene; + this.missingCapabilityDescription = Bindings.createStringBinding(this::getMissingCapabilityDescription, missingCapability); + } + + @FXML + public void back() { + window.setScene(startScene.get()); + } + + /* Getters */ + + public StringBinding missingCapabilityDescriptionProperty() { + return missingCapabilityDescription; + } + + public String getMissingCapabilityDescription() { + FileSystemCapabilityChecker.Capability c = missingCapability.get(); + if (c != null) { + return localization.getString("migration.error.missingFileSystemCapabilities.reason." + c.name()); + } else { + return null; + } + } +} diff --git a/main/ui/src/main/java/org/cryptomator/ui/migration/MigrationModule.java b/main/ui/src/main/java/org/cryptomator/ui/migration/MigrationModule.java index 478bc91a6..7404088e3 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/migration/MigrationModule.java +++ b/main/ui/src/main/java/org/cryptomator/ui/migration/MigrationModule.java @@ -10,6 +10,7 @@ import javafx.scene.Scene; import javafx.scene.image.Image; import javafx.stage.Modality; import javafx.stage.Stage; +import org.cryptomator.cryptofs.common.FileSystemCapabilityChecker; import org.cryptomator.ui.common.DefaultSceneFactory; import org.cryptomator.ui.common.FXMLLoaderFactory; import org.cryptomator.ui.common.FxController; @@ -55,6 +56,13 @@ abstract class MigrationModule { return new SimpleObjectProperty<>(); } + @Provides + @Named("capabilityErrorCause") + @MigrationScoped + static ObjectProperty provideCapabilityErrorCause() { + return new SimpleObjectProperty<>(); + } + @Provides @FxmlScene(FxmlFile.MIGRATION_START) @MigrationScoped @@ -76,6 +84,13 @@ abstract class MigrationModule { return fxmlLoaders.createScene("/fxml/migration_success.fxml"); } + @Provides + @FxmlScene(FxmlFile.MIGRATION_CAPABILITY_ERROR) + @MigrationScoped + static Scene provideMigrationCapabilityErrorScene(@MigrationWindow FXMLLoaderFactory fxmlLoaders) { + return fxmlLoaders.createScene("/fxml/migration_capability_error.fxml"); + } + @Provides @FxmlScene(FxmlFile.MIGRATION_GENERIC_ERROR) @MigrationScoped @@ -83,6 +98,7 @@ abstract class MigrationModule { return fxmlLoaders.createScene("/fxml/migration_generic_error.fxml"); } + // ------------------ @Binds @@ -100,6 +116,11 @@ abstract class MigrationModule { @FxControllerKey(MigrationSuccessController.class) abstract FxController bindMigrationSuccessController(MigrationSuccessController controller); + @Binds + @IntoMap + @FxControllerKey(MigrationCapabilityErrorController.class) + abstract FxController bindMigrationCapabilityErrorController(MigrationCapabilityErrorController controller); + @Binds @IntoMap @FxControllerKey(MigrationGenericErrorController.class) diff --git a/main/ui/src/main/java/org/cryptomator/ui/migration/MigrationRunController.java b/main/ui/src/main/java/org/cryptomator/ui/migration/MigrationRunController.java index 19cdea0fe..81c8f90f7 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/migration/MigrationRunController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/migration/MigrationRunController.java @@ -1,9 +1,6 @@ package org.cryptomator.ui.migration; import dagger.Lazy; -import javafx.animation.KeyFrame; -import javafx.animation.KeyValue; -import javafx.animation.Timeline; import javafx.application.Platform; import javafx.beans.binding.Bindings; import javafx.beans.binding.ObjectBinding; @@ -13,20 +10,15 @@ import javafx.beans.property.ObjectProperty; 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; import javafx.stage.Stage; -import javafx.util.Duration; import org.cryptomator.common.vaults.Vault; import org.cryptomator.common.vaults.VaultState; import org.cryptomator.cryptofs.common.FileSystemCapabilityChecker; 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; import org.cryptomator.keychain.KeychainAccessException; @@ -43,8 +35,6 @@ import javax.inject.Inject; import javax.inject.Named; import java.util.Arrays; import java.util.Optional; -import java.util.Timer; -import java.util.TimerTask; import java.util.concurrent.ExecutorService; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; @@ -62,10 +52,12 @@ public class MigrationRunController implements FxController { private final ExecutorService executor; private final ScheduledExecutorService scheduler; private final Optional keychainAccess; + private final ObjectProperty missingCapability; private final ObjectProperty errorCause; private final Lazy startScene; private final Lazy successScene; private final ObjectBinding migrateButtonContentDisplay; + private final Lazy capabilityErrorScene; private final Lazy genericErrorScene; private final BooleanProperty migrationButtonDisabled; private final DoubleProperty migrationProgress; @@ -73,16 +65,18 @@ public class MigrationRunController implements FxController { public NiceSecurePasswordField passwordField; @Inject - public MigrationRunController(@MigrationWindow Stage window, @MigrationWindow Vault vault, ExecutorService executor, ScheduledExecutorService scheduler, Optional keychainAccess, @Named("genericErrorCause") ObjectProperty errorCause, @FxmlScene(FxmlFile.MIGRATION_START) Lazy startScene, @FxmlScene(FxmlFile.MIGRATION_SUCCESS) Lazy successScene, @FxmlScene(FxmlFile.MIGRATION_GENERIC_ERROR) Lazy genericErrorScene) { + public MigrationRunController(@MigrationWindow Stage window, @MigrationWindow Vault vault, ExecutorService executor, ScheduledExecutorService scheduler, Optional keychainAccess, @Named("capabilityErrorCause") ObjectProperty missingCapability, @Named("genericErrorCause") ObjectProperty errorCause, @FxmlScene(FxmlFile.MIGRATION_START) Lazy startScene, @FxmlScene(FxmlFile.MIGRATION_SUCCESS) Lazy successScene, @FxmlScene(FxmlFile.MIGRATION_CAPABILITY_ERROR) Lazy capabilityErrorScene, @FxmlScene(FxmlFile.MIGRATION_GENERIC_ERROR) Lazy genericErrorScene) { this.window = window; this.vault = vault; this.executor = executor; this.scheduler = scheduler; this.keychainAccess = keychainAccess; + this.missingCapability = missingCapability; this.errorCause = errorCause; this.startScene = startScene; this.successScene = successScene; this.migrateButtonContentDisplay = Bindings.createObjectBinding(this::getMigrateButtonContentDisplay, vault.stateProperty()); + this.capabilityErrorScene = capabilityErrorScene; this.genericErrorScene = genericErrorScene; this.migrationButtonDisabled = new SimpleBooleanProperty(); this.migrationProgress = new SimpleDoubleProperty(volatileMigrationProgress); @@ -115,10 +109,11 @@ public class MigrationRunController implements FxController { 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) { + LOG.info("Migration of '{}' succeeded, but another migration is required.", vault.getDisplayableName()); vault.setState(VaultState.NEEDS_MIGRATION); } else { + LOG.info("Migration of '{}' succeeded.", vault.getDisplayableName()); vault.setState(VaultState.LOCKED); passwordField.swipe(); window.setScene(successScene.get()); @@ -128,10 +123,11 @@ public class MigrationRunController implements FxController { passwordField.selectAll(); passwordField.requestFocus(); vault.setState(VaultState.NEEDS_MIGRATION); - }).onError(NoApplicableMigratorException.class, e -> { - LOG.error("Can not migrate vault.", e); + }).onError(FileSystemCapabilityChecker.MissingCapabilityException.class, e -> { + LOG.error("Underlying file system not supported.", e); vault.setState(VaultState.ERROR); - // TODO show specific error screen + missingCapability.set(e.getMissingCapability()); + window.setScene(capabilityErrorScene.get()); }).onError(Exception.class, e -> { // including RuntimeExceptions LOG.error("Migration failed for technical reasons.", e); vault.setState(VaultState.NEEDS_MIGRATION); diff --git a/main/ui/src/main/java/org/cryptomator/ui/recoverykey/RecoveryKeyCreationController.java b/main/ui/src/main/java/org/cryptomator/ui/recoverykey/RecoveryKeyCreationController.java index 9c9a173c6..d39aee58e 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/recoverykey/RecoveryKeyCreationController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/recoverykey/RecoveryKeyCreationController.java @@ -1,16 +1,10 @@ package org.cryptomator.ui.recoverykey; import dagger.Lazy; -import javafx.animation.KeyFrame; -import javafx.animation.KeyValue; -import javafx.animation.Timeline; -import javafx.beans.property.ReadOnlyStringProperty; import javafx.beans.property.StringProperty; -import javafx.beans.value.WritableValue; import javafx.fxml.FXML; import javafx.scene.Scene; import javafx.stage.Stage; -import javafx.util.Duration; import org.cryptomator.common.vaults.Vault; import org.cryptomator.cryptolib.api.InvalidPassphraseException; import org.cryptomator.ui.common.Animations; @@ -22,7 +16,6 @@ import org.cryptomator.ui.controls.NiceSecurePasswordField; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javax.annotation.Nullable; import javax.inject.Inject; import java.io.IOException; import java.util.concurrent.ExecutorService; diff --git a/main/ui/src/main/java/org/cryptomator/ui/unlock/UnlockController.java b/main/ui/src/main/java/org/cryptomator/ui/unlock/UnlockController.java index 30acd2486..257f185f7 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/unlock/UnlockController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/unlock/UnlockController.java @@ -1,34 +1,27 @@ package org.cryptomator.ui.unlock; import dagger.Lazy; -import javafx.animation.KeyFrame; -import javafx.animation.KeyValue; -import javafx.animation.Timeline; import javafx.beans.binding.Bindings; import javafx.beans.binding.ObjectBinding; import javafx.beans.property.BooleanProperty; import javafx.beans.property.ObjectProperty; import javafx.beans.property.ReadOnlyBooleanProperty; import javafx.beans.property.SimpleBooleanProperty; -import javafx.beans.value.WritableValue; import javafx.concurrent.Task; import javafx.fxml.FXML; import javafx.scene.Scene; import javafx.scene.control.CheckBox; import javafx.scene.control.ContentDisplay; import javafx.stage.Stage; -import javafx.util.Duration; import org.cryptomator.common.vaults.Vault; import org.cryptomator.common.vaults.VaultState; import org.cryptomator.cryptolib.api.InvalidPassphraseException; -import org.cryptomator.cryptolib.api.UnsupportedVaultFormatException; import org.cryptomator.keychain.KeychainAccess; import org.cryptomator.keychain.KeychainAccessException; import org.cryptomator.ui.common.Animations; import org.cryptomator.ui.common.FxController; import org.cryptomator.ui.common.FxmlFile; import org.cryptomator.ui.common.FxmlScene; -import org.cryptomator.ui.common.Tasks; import org.cryptomator.ui.common.VaultService; import org.cryptomator.ui.controls.NiceSecurePasswordField; import org.cryptomator.ui.forgetPassword.ForgetPasswordComponent; diff --git a/main/ui/src/main/resources/fxml/migration_capability_error.fxml b/main/ui/src/main/resources/fxml/migration_capability_error.fxml new file mode 100644 index 000000000..af2135834 --- /dev/null +++ b/main/ui/src/main/resources/fxml/migration_capability_error.fxml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +