From 7fc5b1e55fde554ab83374388bba059fa0d99290 Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Tue, 10 Mar 2020 09:25:15 +0100 Subject: [PATCH] Refactored handling of unexpected errors --- .../AddVaultGenericErrorController.java | 48 ------------------- .../ui/addvaultwizard/AddVaultModule.java | 37 +------------- .../ChooseExistingVaultController.java | 12 ++--- .../CreateNewVaultLocationController.java | 12 ++--- .../CreateNewVaultPasswordController.java | 23 +++------ .../cryptomator/ui/common/ErrorComponent.java | 40 ++++++++++++++++ .../ui/common/ErrorController.java | 45 +++++++++++++++++ .../cryptomator/ui/common/ErrorModule.java | 45 +++++++++++++++++ .../ui/common/FXMLLoaderFactory.java | 7 ++- .../org/cryptomator/ui/common/FxmlFile.java | 4 +- .../ui/common/StackTraceController.java | 28 ----------- .../ui/fxapp/FxApplicationModule.java | 3 +- .../MigrationGenericErrorController.java | 29 ----------- .../ui/migration/MigrationModule.java | 32 +------------ .../ui/migration/MigrationRunController.java | 12 ++--- .../ui/unlock/UnlockController.java | 12 ++--- .../unlock/UnlockGenericErrorController.java | 29 ----------- .../cryptomator/ui/unlock/UnlockModule.java | 32 ------------- .../fxml/addvault_generic_error.fxml | 27 ----------- .../fxml/{stacktrace.fxml => error.fxml} | 27 ++++++++--- .../fxml/migration_generic_error.fxml | 32 ------------- .../resources/fxml/unlock_generic_error.fxml | 32 ------------- 22 files changed, 188 insertions(+), 380 deletions(-) delete mode 100644 main/ui/src/main/java/org/cryptomator/ui/addvaultwizard/AddVaultGenericErrorController.java create mode 100644 main/ui/src/main/java/org/cryptomator/ui/common/ErrorComponent.java create mode 100644 main/ui/src/main/java/org/cryptomator/ui/common/ErrorController.java create mode 100644 main/ui/src/main/java/org/cryptomator/ui/common/ErrorModule.java delete mode 100644 main/ui/src/main/java/org/cryptomator/ui/common/StackTraceController.java delete mode 100644 main/ui/src/main/java/org/cryptomator/ui/migration/MigrationGenericErrorController.java delete mode 100644 main/ui/src/main/java/org/cryptomator/ui/unlock/UnlockGenericErrorController.java delete mode 100644 main/ui/src/main/resources/fxml/addvault_generic_error.fxml rename main/ui/src/main/resources/fxml/{stacktrace.fxml => error.fxml} (60%) delete mode 100644 main/ui/src/main/resources/fxml/migration_generic_error.fxml delete mode 100644 main/ui/src/main/resources/fxml/unlock_generic_error.fxml diff --git a/main/ui/src/main/java/org/cryptomator/ui/addvaultwizard/AddVaultGenericErrorController.java b/main/ui/src/main/java/org/cryptomator/ui/addvaultwizard/AddVaultGenericErrorController.java deleted file mode 100644 index 299f183f3..000000000 --- a/main/ui/src/main/java/org/cryptomator/ui/addvaultwizard/AddVaultGenericErrorController.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.cryptomator.ui.addvaultwizard; - -import javafx.beans.binding.BooleanBinding; -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.ui.common.FxController; - -import javax.inject.Inject; -import javax.inject.Named; - -@AddVaultWizardScoped -public class AddVaultGenericErrorController implements FxController { - - private final Stage window; - private final ReadOnlyObjectProperty previousScene; - private final BooleanBinding returnToPreviousSceneAllowed; - - @Inject - AddVaultGenericErrorController(@AddVaultWizardWindow Stage window, @Named("genericErrorReturnScene") ObjectProperty previousScene) { - this.window = window; - this.previousScene = previousScene; - this.returnToPreviousSceneAllowed = previousScene.isNotNull(); - } - - @FXML - public void back() { - assert previousScene.get() != null; // otherwise button should be disabled - window.setScene(previousScene.get()); - } - - @FXML - public void close(){ - window.close(); - } - - /* Getter/Setter */ - - public BooleanBinding returnToPreviousSceneAllowedProperty() { - return returnToPreviousSceneAllowed; - } - - public boolean isReturnToPreviousSceneAllowed() { - return returnToPreviousSceneAllowed.get(); - } -} diff --git a/main/ui/src/main/java/org/cryptomator/ui/addvaultwizard/AddVaultModule.java b/main/ui/src/main/java/org/cryptomator/ui/addvaultwizard/AddVaultModule.java index b1a99cf75..08f499c92 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/addvaultwizard/AddVaultModule.java +++ b/main/ui/src/main/java/org/cryptomator/ui/addvaultwizard/AddVaultModule.java @@ -21,7 +21,6 @@ import org.cryptomator.ui.common.FxmlFile; import org.cryptomator.ui.common.FxmlScene; import org.cryptomator.ui.common.NewPasswordController; import org.cryptomator.ui.common.PasswordStrengthUtil; -import org.cryptomator.ui.common.StackTraceController; import org.cryptomator.ui.mainwindow.MainWindow; import org.cryptomator.ui.recoverykey.RecoveryKeyDisplayController; @@ -62,20 +61,6 @@ public abstract class AddVaultModule { return stage; } - @Provides - @Named("genericErrorCause") - @AddVaultWizardScoped - static ObjectProperty provideGenericErrorCause() { - return new SimpleObjectProperty<>(); - } - - @Provides - @Named("genericErrorReturnScene") - @AddVaultWizardScoped - static ObjectProperty provideGenericErrorReturnScene() { - return new SimpleObjectProperty<>(); - } - @Provides @AddVaultWizardScoped static ObjectProperty provideVaultPath() { @@ -118,14 +103,7 @@ public abstract class AddVaultModule { static Scene provideChooseExistingVaultScene(@AddVaultWizardWindow FXMLLoaderFactory fxmlLoaders) { return fxmlLoaders.createScene(FxmlFile.ADDVAULT_EXISTING.getRessourcePathString()); } - - @Provides - @FxmlScene(FxmlFile.ADDVAULT_GENERIC_ERROR) - @AddVaultWizardScoped - static Scene provideGenericErrorScene(@AddVaultWizardWindow FXMLLoaderFactory fxmlLoaders) { - return fxmlLoaders.createScene(FxmlFile.ADDVAULT_GENERIC_ERROR.getRessourcePathString()); - } - + @Provides @FxmlScene(FxmlFile.ADDVAULT_NEW_NAME) @AddVaultWizardScoped @@ -211,16 +189,5 @@ public abstract class AddVaultModule { @IntoMap @FxControllerKey(AddVaultSuccessController.class) abstract FxController bindAddVaultSuccessController(AddVaultSuccessController controller); - - @Binds - @IntoMap - @FxControllerKey(AddVaultGenericErrorController.class) - abstract FxController bindAddVaultGenericErrorController(AddVaultGenericErrorController controller); - - @Provides - @IntoMap - @FxControllerKey(StackTraceController.class) - static FxController provideStackTraceController(@Named("genericErrorCause") ObjectProperty errorCause) { - return new StackTraceController(errorCause.get()); - } + } diff --git a/main/ui/src/main/java/org/cryptomator/ui/addvaultwizard/ChooseExistingVaultController.java b/main/ui/src/main/java/org/cryptomator/ui/addvaultwizard/ChooseExistingVaultController.java index 3951cfbee..5e0ab64fa 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/addvaultwizard/ChooseExistingVaultController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/addvaultwizard/ChooseExistingVaultController.java @@ -8,6 +8,7 @@ import javafx.stage.FileChooser; import javafx.stage.Stage; import org.cryptomator.common.vaults.Vault; import org.cryptomator.common.vaults.VaultListManager; +import org.cryptomator.ui.common.ErrorComponent; import org.cryptomator.ui.common.FxController; import org.cryptomator.ui.common.FxmlFile; import org.cryptomator.ui.common.FxmlScene; @@ -29,20 +30,18 @@ public class ChooseExistingVaultController implements FxController { private final Stage window; private final Lazy welcomeScene; private final Lazy successScene; - private final Lazy genericErrorScene; - private final ObjectProperty genericErrorCause; + private final ErrorComponent.Builder errorComponent; private final ObjectProperty vaultPath; private final ObjectProperty vault; private final VaultListManager vaultListManager; private final ResourceBundle resourceBundle; @Inject - ChooseExistingVaultController(@AddVaultWizardWindow Stage window, @FxmlScene(FxmlFile.ADDVAULT_WELCOME) Lazy welcomeScene, @FxmlScene(FxmlFile.ADDVAULT_SUCCESS) Lazy successScene, @FxmlScene(FxmlFile.ADDVAULT_GENERIC_ERROR) Lazy genericErrorScene, @Named("genericErrorCause") ObjectProperty genericErrorCause, ObjectProperty vaultPath, @AddVaultWizardWindow ObjectProperty vault, VaultListManager vaultListManager, ResourceBundle resourceBundle) { + ChooseExistingVaultController(@AddVaultWizardWindow Stage window, @FxmlScene(FxmlFile.ADDVAULT_WELCOME) Lazy welcomeScene, @FxmlScene(FxmlFile.ADDVAULT_SUCCESS) Lazy successScene, ErrorComponent.Builder errorComponent, ObjectProperty vaultPath, @AddVaultWizardWindow ObjectProperty vault, VaultListManager vaultListManager, ResourceBundle resourceBundle) { this.window = window; this.welcomeScene = welcomeScene; this.successScene = successScene; - this.genericErrorScene = genericErrorScene; - this.genericErrorCause = genericErrorCause; + this.errorComponent = errorComponent; this.vaultPath = vaultPath; this.vault = vault; this.vaultListManager = vaultListManager; @@ -68,8 +67,7 @@ public class ChooseExistingVaultController implements FxController { window.setScene(successScene.get()); } catch (NoSuchFileException e) { LOG.error("Failed to open existing vault.", e); - genericErrorCause.set(e); - window.setScene(genericErrorScene.get()); + errorComponent.cause(e).window(window).returnToScene(window.getScene()).build().showErrorScene(); } } } diff --git a/main/ui/src/main/java/org/cryptomator/ui/addvaultwizard/CreateNewVaultLocationController.java b/main/ui/src/main/java/org/cryptomator/ui/addvaultwizard/CreateNewVaultLocationController.java index f3730be19..51b70f470 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/addvaultwizard/CreateNewVaultLocationController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/addvaultwizard/CreateNewVaultLocationController.java @@ -16,6 +16,7 @@ import javafx.scene.control.Toggle; import javafx.scene.control.ToggleGroup; import javafx.stage.DirectoryChooser; import javafx.stage.Stage; +import org.cryptomator.ui.common.ErrorComponent; import org.cryptomator.ui.common.FxController; import org.cryptomator.ui.common.FxmlFile; import org.cryptomator.ui.common.FxmlScene; @@ -41,8 +42,7 @@ public class CreateNewVaultLocationController implements FxController { private final Stage window; private final Lazy chooseNameScene; private final Lazy choosePasswordScene; - private final Lazy genericErrorScene; - private final ObjectProperty genericErrorCause; + private final ErrorComponent.Builder errorComponent; private final LocationPresets locationPresets; private final ObjectProperty vaultPath; private final StringProperty vaultName; @@ -61,12 +61,11 @@ public class CreateNewVaultLocationController implements FxController { public RadioButton customRadioButton; @Inject - CreateNewVaultLocationController(@AddVaultWizardWindow Stage window, @FxmlScene(FxmlFile.ADDVAULT_NEW_NAME) Lazy chooseNameScene, @FxmlScene(FxmlFile.ADDVAULT_NEW_PASSWORD) Lazy choosePasswordScene, @FxmlScene(FxmlFile.ADDVAULT_GENERIC_ERROR) Lazy genericErrorScene, @Named("genericErrorCause") ObjectProperty genericErrorCause, LocationPresets locationPresets, ObjectProperty vaultPath, @Named("vaultName") StringProperty vaultName, ResourceBundle resourceBundle) { + CreateNewVaultLocationController(@AddVaultWizardWindow Stage window, @FxmlScene(FxmlFile.ADDVAULT_NEW_NAME) Lazy chooseNameScene, @FxmlScene(FxmlFile.ADDVAULT_NEW_PASSWORD) Lazy choosePasswordScene, ErrorComponent.Builder errorComponent, LocationPresets locationPresets, ObjectProperty vaultPath, @Named("vaultName") StringProperty vaultName, ResourceBundle resourceBundle) { this.window = window; this.chooseNameScene = chooseNameScene; this.choosePasswordScene = choosePasswordScene; - this.genericErrorScene = genericErrorScene; - this.genericErrorCause = genericErrorCause; + this.errorComponent = errorComponent; this.locationPresets = locationPresets; this.vaultPath = vaultPath; this.vaultName = vaultName; @@ -128,8 +127,7 @@ public class CreateNewVaultLocationController implements FxController { warningText.set(resourceBundle.getString("addvaultwizard.new.fileAlreadyExists")); } catch (IOException e) { LOG.error("Failed to create and delete directory at chosen vault path.", e); - genericErrorCause.set(e); - window.setScene(genericErrorScene.get()); + errorComponent.cause(e).window(window).returnToScene(window.getScene()).build().showErrorScene(); } } diff --git a/main/ui/src/main/java/org/cryptomator/ui/addvaultwizard/CreateNewVaultPasswordController.java b/main/ui/src/main/java/org/cryptomator/ui/addvaultwizard/CreateNewVaultPasswordController.java index 845145908..2c2f3885a 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/addvaultwizard/CreateNewVaultPasswordController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/addvaultwizard/CreateNewVaultPasswordController.java @@ -18,6 +18,7 @@ import org.cryptomator.common.vaults.Vault; import org.cryptomator.common.vaults.VaultListManager; import org.cryptomator.cryptofs.CryptoFileSystemProperties; import org.cryptomator.cryptofs.CryptoFileSystemProvider; +import org.cryptomator.ui.common.ErrorComponent; import org.cryptomator.ui.common.FxController; import org.cryptomator.ui.common.FxmlFile; import org.cryptomator.ui.common.FxmlScene; @@ -53,9 +54,7 @@ public class CreateNewVaultPasswordController implements FxController { private final Lazy chooseLocationScene; private final Lazy recoveryKeyScene; private final Lazy successScene; - private final Lazy genericErrorScene; - private final ObjectProperty genericErrorCause; - private final ObjectProperty genericErrorReturnScene; + private final ErrorComponent.Builder errorComponent; private final ExecutorService executor; private final RecoveryKeyFactory recoveryKeyFactory; private final StringProperty vaultNameProperty; @@ -75,14 +74,12 @@ public class CreateNewVaultPasswordController implements FxController { public Toggle skipRecoveryKey; @Inject - CreateNewVaultPasswordController(@AddVaultWizardWindow Stage window, @FxmlScene(FxmlFile.ADDVAULT_NEW_LOCATION) Lazy chooseLocationScene, @FxmlScene(FxmlFile.ADDVAULT_NEW_RECOVERYKEY) Lazy recoveryKeyScene, @FxmlScene(FxmlFile.ADDVAULT_SUCCESS) Lazy successScene, @FxmlScene(FxmlFile.ADDVAULT_GENERIC_ERROR) Lazy genericErrorScene, @Named("genericErrorCause") ObjectProperty genericErrorCause, @Named("genericErrorReturnScene") ObjectProperty genericErrorReturnScene, ExecutorService executor, RecoveryKeyFactory recoveryKeyFactory, @Named("vaultName") StringProperty vaultName, ObjectProperty vaultPath, @AddVaultWizardWindow ObjectProperty vault, @Named("recoveryKey") StringProperty recoveryKey, VaultListManager vaultListManager, ResourceBundle resourceBundle, @Named("newPassword") ObjectProperty password, ReadmeGenerator readmeGenerator) { + CreateNewVaultPasswordController(@AddVaultWizardWindow Stage window, @FxmlScene(FxmlFile.ADDVAULT_NEW_LOCATION) Lazy chooseLocationScene, @FxmlScene(FxmlFile.ADDVAULT_NEW_RECOVERYKEY) Lazy recoveryKeyScene, @FxmlScene(FxmlFile.ADDVAULT_SUCCESS) Lazy successScene, ErrorComponent.Builder errorComponent, ExecutorService executor, RecoveryKeyFactory recoveryKeyFactory, @Named("vaultName") StringProperty vaultName, ObjectProperty vaultPath, @AddVaultWizardWindow ObjectProperty vault, @Named("recoveryKey") StringProperty recoveryKey, VaultListManager vaultListManager, ResourceBundle resourceBundle, @Named("newPassword") ObjectProperty password, ReadmeGenerator readmeGenerator) { this.window = window; this.chooseLocationScene = chooseLocationScene; this.recoveryKeyScene = recoveryKeyScene; this.successScene = successScene; - this.genericErrorScene = genericErrorScene; - this.genericErrorCause = genericErrorCause; - this.genericErrorReturnScene = genericErrorReturnScene; + this.errorComponent = errorComponent; this.executor = executor; this.recoveryKeyFactory = recoveryKeyFactory; this.vaultNameProperty = vaultName; @@ -117,9 +114,7 @@ public class CreateNewVaultPasswordController implements FxController { Files.createDirectory(pathToVault); } catch (IOException e) { LOG.error("Failed to create vault directory.", e); - genericErrorReturnScene.set(window.getScene()); - genericErrorCause.set(e); - window.setScene(genericErrorScene.get()); + errorComponent.cause(e).window(window).returnToScene(window.getScene()).build().showErrorScene(); return; } @@ -144,9 +139,7 @@ public class CreateNewVaultPasswordController implements FxController { window.setScene(recoveryKeyScene.get()); }).onError(IOException.class, e -> { LOG.error("Failed to initialize vault.", e); - genericErrorReturnScene.set(window.getScene()); - genericErrorCause.set(e); - window.setScene(genericErrorScene.get()); + errorComponent.cause(e).window(window).returnToScene(window.getScene()).build().showErrorScene(); }).andFinally(() -> { processing.set(false); }).runOnce(executor); @@ -162,9 +155,7 @@ public class CreateNewVaultPasswordController implements FxController { window.setScene(successScene.get()); }).onError(IOException.class, e -> { LOG.error("Failed to initialize vault.", e); - genericErrorReturnScene.set(window.getScene()); - genericErrorCause.set(e); - window.setScene(genericErrorScene.get()); + errorComponent.cause(e).window(window).returnToScene(window.getScene()).build().showErrorScene(); }).andFinally(() -> { processing.set(false); }).runOnce(executor); diff --git a/main/ui/src/main/java/org/cryptomator/ui/common/ErrorComponent.java b/main/ui/src/main/java/org/cryptomator/ui/common/ErrorComponent.java new file mode 100644 index 000000000..0ba4e4d47 --- /dev/null +++ b/main/ui/src/main/java/org/cryptomator/ui/common/ErrorComponent.java @@ -0,0 +1,40 @@ +package org.cryptomator.ui.common; + +import dagger.BindsInstance; +import dagger.Subcomponent; +import javafx.scene.Scene; +import javafx.stage.Stage; + +import javax.annotation.Nullable; + +@Subcomponent(modules = {ErrorModule.class}) +public interface ErrorComponent { + + Stage window(); + + @FxmlScene(FxmlFile.ERROR) + Scene scene(); + + default void showErrorScene() { + Stage stage = window(); + stage.setScene(scene()); + stage.show(); + } + + @Subcomponent.Builder + interface Builder { + + @BindsInstance + Builder cause(Throwable cause); + + @BindsInstance + Builder window(Stage window); + + @BindsInstance + Builder returnToScene(@Nullable Scene previousScene); + + ErrorComponent build(); + + } + +} diff --git a/main/ui/src/main/java/org/cryptomator/ui/common/ErrorController.java b/main/ui/src/main/java/org/cryptomator/ui/common/ErrorController.java new file mode 100644 index 000000000..52c3d4034 --- /dev/null +++ b/main/ui/src/main/java/org/cryptomator/ui/common/ErrorController.java @@ -0,0 +1,45 @@ +package org.cryptomator.ui.common; + +import javafx.fxml.FXML; +import javafx.scene.Scene; +import javafx.stage.Stage; + +import javax.annotation.Nullable; +import javax.inject.Inject; +import javax.inject.Named; + +public class ErrorController implements FxController { + + private final String stackTrace; + private final Scene previousScene; + private final Stage window; + + @Inject + ErrorController(@Named("stackTrace") String stackTrace, @Nullable Scene previousScene, Stage window) { + this.stackTrace = stackTrace; + this.previousScene = previousScene; + this.window = window; + } + + @FXML + public void back() { + if (previousScene != null) { + window.setScene(previousScene); + } + } + + @FXML + public void close() { + window.close(); + } + + /* Getter/Setter */ + + public boolean isPreviousScenePresent() { + return previousScene != null; + } + + public String getStackTrace() { + return stackTrace; + } +} diff --git a/main/ui/src/main/java/org/cryptomator/ui/common/ErrorModule.java b/main/ui/src/main/java/org/cryptomator/ui/common/ErrorModule.java new file mode 100644 index 000000000..9b272a585 --- /dev/null +++ b/main/ui/src/main/java/org/cryptomator/ui/common/ErrorModule.java @@ -0,0 +1,45 @@ +package org.cryptomator.ui.common; + +import dagger.Binds; +import dagger.Module; +import dagger.Provides; +import dagger.multibindings.IntoMap; +import javafx.scene.Scene; + +import javax.inject.Named; +import javax.inject.Provider; +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.nio.charset.StandardCharsets; +import java.util.Map; +import java.util.ResourceBundle; + +@Module +abstract class ErrorModule { + + @Provides + static FXMLLoaderFactory provideFxmlLoaderFactory(Map, Provider> factories, DefaultSceneFactory sceneFactory, ResourceBundle resourceBundle) { + return new FXMLLoaderFactory(factories, sceneFactory, resourceBundle); + } + + @Provides + @Named("stackTrace") + static String provideStackTrace(Throwable cause) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + cause.printStackTrace(new PrintStream(baos)); + return baos.toString(StandardCharsets.UTF_8); + } + + @Binds + @IntoMap + @FxControllerKey(ErrorController.class) + abstract FxController bindErrorController(ErrorController controller); + + @Provides + @FxmlScene(FxmlFile.ERROR) + static Scene provideErrorScene(FXMLLoaderFactory fxmlLoaders) { + return fxmlLoaders.createScene(FxmlFile.ERROR.getRessourcePathString()); + } + + +} diff --git a/main/ui/src/main/java/org/cryptomator/ui/common/FXMLLoaderFactory.java b/main/ui/src/main/java/org/cryptomator/ui/common/FXMLLoaderFactory.java index 1edcc633b..210655a5f 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/common/FXMLLoaderFactory.java +++ b/main/ui/src/main/java/org/cryptomator/ui/common/FXMLLoaderFactory.java @@ -1,6 +1,5 @@ package org.cryptomator.ui.common; -import com.google.common.base.Splitter; import javafx.fxml.FXMLLoader; import javafx.scene.Parent; import javafx.scene.Scene; @@ -9,7 +8,6 @@ import javax.inject.Provider; import java.io.IOException; import java.io.InputStream; import java.io.UncheckedIOException; -import java.util.List; import java.util.Map; import java.util.ResourceBundle; import java.util.function.Function; @@ -65,8 +63,9 @@ public class FXMLLoaderFactory { throw new UncheckedIOException("Failed to load " + fxmlResourceName, e); } Parent root = loader.getRoot(); - List addtionalStyleSheets = Splitter.on(',').omitEmptyStrings().splitToList(resourceBundle.getString("additionalStyleSheets")); - addtionalStyleSheets.forEach(styleSheet -> root.getStylesheets().add("/css/" + styleSheet)); + // TODO: discuss if we can remove language-specific stylesheets + // List addtionalStyleSheets = Splitter.on(',').omitEmptyStrings().splitToList(resourceBundle.getString("additionalStyleSheets")); + // addtionalStyleSheets.forEach(styleSheet -> root.getStylesheets().add("/css/" + styleSheet)); return sceneFactory.apply(root); } 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 5ff125cc9..9798a9a0f 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 @@ -2,7 +2,6 @@ package org.cryptomator.ui.common; public enum FxmlFile { ADDVAULT_EXISTING("/fxml/addvault_existing.fxml"), // - ADDVAULT_GENERIC_ERROR("/fxml/addvault_generic_error.fxml"), ADDVAULT_NEW_NAME("/fxml/addvault_new_name.fxml"), // ADDVAULT_NEW_LOCATION("/fxml/addvault_new_location.fxml"), // ADDVAULT_NEW_PASSWORD("/fxml/addvault_new_password.fxml"), // @@ -10,10 +9,10 @@ public enum FxmlFile { ADDVAULT_SUCCESS("/fxml/addvault_success.fxml"), // ADDVAULT_WELCOME("/fxml/addvault_welcome.fxml"), // CHANGEPASSWORD("/fxml/changepassword.fxml"), // + ERROR("/fxml/error.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"), // MIGRATION_SUCCESS("/fxml/migration_success.fxml"), // @@ -25,7 +24,6 @@ public enum FxmlFile { RECOVERYKEY_SUCCESS("/fxml/recoverykey_success.fxml"), // REMOVE_VAULT("/fxml/remove_vault.fxml"), // UNLOCK("/fxml/unlock.fxml"), - UNLOCK_GENERIC_ERROR("/fxml/unlock_generic_error.fxml"), // UNLOCK_INVALID_MOUNT_POINT("/fxml/unlock_invalid_mount_point.fxml"), // UNLOCK_SUCCESS("/fxml/unlock_success.fxml"), // VAULT_OPTIONS("/fxml/vault_options.fxml"), // diff --git a/main/ui/src/main/java/org/cryptomator/ui/common/StackTraceController.java b/main/ui/src/main/java/org/cryptomator/ui/common/StackTraceController.java deleted file mode 100644 index f83614dc1..000000000 --- a/main/ui/src/main/java/org/cryptomator/ui/common/StackTraceController.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.cryptomator.ui.common; - -import java.io.ByteArrayOutputStream; -import java.io.PrintStream; -import java.nio.charset.StandardCharsets; - -public class StackTraceController implements FxController { - - private final String stackTrace; - - public StackTraceController(Throwable cause) { - this.stackTrace = provideStackTrace(cause); - } - - private static String provideStackTrace(Throwable cause) { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - cause.printStackTrace(new PrintStream(baos)); - return baos.toString(StandardCharsets.UTF_8); - } - - /* Getter/Setter */ - - public String getStackTrace() { - return stackTrace; - } - - -} diff --git a/main/ui/src/main/java/org/cryptomator/ui/fxapp/FxApplicationModule.java b/main/ui/src/main/java/org/cryptomator/ui/fxapp/FxApplicationModule.java index 5a12822b2..4fd18202d 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/fxapp/FxApplicationModule.java +++ b/main/ui/src/main/java/org/cryptomator/ui/fxapp/FxApplicationModule.java @@ -14,6 +14,7 @@ import javafx.beans.property.SimpleObjectProperty; import javafx.scene.image.Image; import org.apache.commons.lang3.SystemUtils; import org.cryptomator.common.vaults.Vault; +import org.cryptomator.ui.common.ErrorComponent; import org.cryptomator.ui.mainwindow.MainWindowComponent; import org.cryptomator.ui.preferences.PreferencesComponent; import org.cryptomator.ui.quit.QuitComponent; @@ -26,7 +27,7 @@ import java.io.UncheckedIOException; import java.util.Collections; import java.util.List; -@Module(includes = {UpdateCheckerModule.class}, subcomponents = {MainWindowComponent.class, PreferencesComponent.class, UnlockComponent.class, QuitComponent.class}) +@Module(includes = {UpdateCheckerModule.class}, subcomponents = {MainWindowComponent.class, PreferencesComponent.class, UnlockComponent.class, QuitComponent.class, ErrorComponent.class}) abstract class FxApplicationModule { @Provides diff --git a/main/ui/src/main/java/org/cryptomator/ui/migration/MigrationGenericErrorController.java b/main/ui/src/main/java/org/cryptomator/ui/migration/MigrationGenericErrorController.java deleted file mode 100644 index 3b6121c79..000000000 --- a/main/ui/src/main/java/org/cryptomator/ui/migration/MigrationGenericErrorController.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.cryptomator.ui.migration; - -import dagger.Lazy; -import javafx.fxml.FXML; -import javafx.scene.Scene; -import javafx.stage.Stage; -import org.cryptomator.ui.common.FxController; -import org.cryptomator.ui.common.FxmlFile; -import org.cryptomator.ui.common.FxmlScene; - -import javax.inject.Inject; - -@MigrationScoped -public class MigrationGenericErrorController implements FxController { - - private final Stage window; - private final Lazy startScene; - - @Inject - MigrationGenericErrorController(@MigrationWindow Stage window, @FxmlScene(FxmlFile.MIGRATION_START) Lazy startScene) { - this.window = window; - this.startScene = startScene; - } - - @FXML - public void back() { - window.setScene(startScene.get()); - } -} 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 7404088e3..508777364 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 @@ -17,7 +17,6 @@ import org.cryptomator.ui.common.FxController; import org.cryptomator.ui.common.FxControllerKey; import org.cryptomator.ui.common.FxmlFile; import org.cryptomator.ui.common.FxmlScene; -import org.cryptomator.ui.common.StackTraceController; import org.cryptomator.ui.mainwindow.MainWindow; import javax.inject.Named; @@ -48,14 +47,7 @@ abstract class MigrationModule { stage.getIcons().addAll(windowIcons); return stage; } - - @Provides - @Named("genericErrorCause") - @MigrationScoped - static ObjectProperty provideGenericErrorCause() { - return new SimpleObjectProperty<>(); - } - + @Provides @Named("capabilityErrorCause") @MigrationScoped @@ -91,14 +83,6 @@ abstract class MigrationModule { return fxmlLoaders.createScene("/fxml/migration_capability_error.fxml"); } - @Provides - @FxmlScene(FxmlFile.MIGRATION_GENERIC_ERROR) - @MigrationScoped - static Scene provideMigrationGenericErrorScene(@MigrationWindow FXMLLoaderFactory fxmlLoaders) { - return fxmlLoaders.createScene("/fxml/migration_generic_error.fxml"); - } - - // ------------------ @Binds @@ -120,17 +104,5 @@ abstract class MigrationModule { @IntoMap @FxControllerKey(MigrationCapabilityErrorController.class) abstract FxController bindMigrationCapabilityErrorController(MigrationCapabilityErrorController controller); - - @Binds - @IntoMap - @FxControllerKey(MigrationGenericErrorController.class) - abstract FxController bindMigrationGenericErrorController(MigrationGenericErrorController controller); - - @Provides - @IntoMap - @FxControllerKey(StackTraceController.class) - static FxController provideStackTraceController(@Named("genericErrorCause") ObjectProperty errorCause) { - return new StackTraceController(errorCause.get()); - } - + } 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 1ca2c90bc..826fa6053 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 @@ -23,6 +23,7 @@ import org.cryptomator.cryptolib.api.InvalidPassphraseException; import org.cryptomator.keychain.KeychainAccess; import org.cryptomator.keychain.KeychainAccessException; import org.cryptomator.ui.common.Animations; +import org.cryptomator.ui.common.ErrorComponent; import org.cryptomator.ui.common.FxController; import org.cryptomator.ui.common.FxmlFile; import org.cryptomator.ui.common.FxmlScene; @@ -54,31 +55,29 @@ public class MigrationRunController implements FxController { private final ScheduledExecutorService scheduler; private final Optional keychainAccess; private final ObjectProperty missingCapability; - private final ObjectProperty errorCause; + private final ErrorComponent.Builder errorComponent; 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; private volatile double volatileMigrationProgress = -1.0; public NiceSecurePasswordField passwordField; @Inject - 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) { + public MigrationRunController(@MigrationWindow Stage window, @MigrationWindow Vault vault, ExecutorService executor, ScheduledExecutorService scheduler, Optional keychainAccess, @Named("capabilityErrorCause") ObjectProperty missingCapability, @FxmlScene(FxmlFile.MIGRATION_START) Lazy startScene, @FxmlScene(FxmlFile.MIGRATION_SUCCESS) Lazy successScene, @FxmlScene(FxmlFile.MIGRATION_CAPABILITY_ERROR) Lazy capabilityErrorScene, ErrorComponent.Builder errorComponent) { this.window = window; this.vault = vault; this.executor = executor; this.scheduler = scheduler; this.keychainAccess = keychainAccess; this.missingCapability = missingCapability; - this.errorCause = errorCause; + this.errorComponent = errorComponent; 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); } @@ -132,8 +131,7 @@ public class MigrationRunController implements FxController { }).onError(Exception.class, e -> { // including RuntimeExceptions LOG.error("Migration failed for technical reasons.", e); vault.setState(VaultState.NEEDS_MIGRATION); - errorCause.set(e); - window.setScene(genericErrorScene.get()); + errorComponent.cause(e).window(window).returnToScene(startScene.get()).build().showErrorScene(); }).andFinally(() -> { progressSyncTask.cancel(true); }).runOnce(executor); 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 257f185f7..f06a03621 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 @@ -19,6 +19,7 @@ import org.cryptomator.cryptolib.api.InvalidPassphraseException; import org.cryptomator.keychain.KeychainAccess; import org.cryptomator.keychain.KeychainAccessException; import org.cryptomator.ui.common.Animations; +import org.cryptomator.ui.common.ErrorComponent; import org.cryptomator.ui.common.FxController; import org.cryptomator.ui.common.FxmlFile; import org.cryptomator.ui.common.FxmlScene; @@ -49,15 +50,14 @@ public class UnlockController implements FxController { private final VaultService vaultService; private final Lazy successScene; private final Lazy invalidMountPointScene; - private final Lazy genericErrorScene; - private final ObjectProperty genericErrorCause; + private final ErrorComponent.Builder errorComponent; private final ForgetPasswordComponent.Builder forgetPassword; private final BooleanProperty unlockButtonDisabled; public NiceSecurePasswordField passwordField; public CheckBox savePassword; @Inject - public UnlockController(@UnlockWindow Stage window, @UnlockWindow Vault vault, ExecutorService executor, Optional keychainAccess, VaultService vaultService, @FxmlScene(FxmlFile.UNLOCK_SUCCESS) Lazy successScene, @FxmlScene(FxmlFile.UNLOCK_INVALID_MOUNT_POINT) Lazy invalidMountPointScene, @FxmlScene(FxmlFile.UNLOCK_GENERIC_ERROR) Lazy genericErrorScene, @Named("genericErrorCause") ObjectProperty genericErrorCause, ForgetPasswordComponent.Builder forgetPassword) { + public UnlockController(@UnlockWindow Stage window, @UnlockWindow Vault vault, ExecutorService executor, Optional keychainAccess, VaultService vaultService, @FxmlScene(FxmlFile.UNLOCK_SUCCESS) Lazy successScene, @FxmlScene(FxmlFile.UNLOCK_INVALID_MOUNT_POINT) Lazy invalidMountPointScene, ErrorComponent.Builder errorComponent, ForgetPasswordComponent.Builder forgetPassword) { this.window = window; this.vault = vault; this.executor = executor; @@ -66,8 +66,7 @@ public class UnlockController implements FxController { this.vaultService = vaultService; this.successScene = successScene; this.invalidMountPointScene = invalidMountPointScene; - this.genericErrorScene = genericErrorScene; - this.genericErrorCause = genericErrorCause; + this.errorComponent = errorComponent; this.forgetPassword = forgetPassword; this.unlockButtonDisabled = new SimpleBooleanProperty(); } @@ -116,8 +115,7 @@ public class UnlockController implements FxController { window.setScene(invalidMountPointScene.get()); } else { LOG.error("Unlock failed for technical reasons.", task.getException()); - genericErrorCause.set(task.getException()); - window.setScene(genericErrorScene.get()); + errorComponent.cause(task.getException()).window(window).returnToScene(window.getScene()).build().showErrorScene(); } }); executor.execute(task); diff --git a/main/ui/src/main/java/org/cryptomator/ui/unlock/UnlockGenericErrorController.java b/main/ui/src/main/java/org/cryptomator/ui/unlock/UnlockGenericErrorController.java deleted file mode 100644 index faa357969..000000000 --- a/main/ui/src/main/java/org/cryptomator/ui/unlock/UnlockGenericErrorController.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.cryptomator.ui.unlock; - -import dagger.Lazy; -import javafx.fxml.FXML; -import javafx.scene.Scene; -import javafx.stage.Stage; -import org.cryptomator.ui.common.FxController; -import org.cryptomator.ui.common.FxmlFile; -import org.cryptomator.ui.common.FxmlScene; - -import javax.inject.Inject; - -@UnlockScoped -public class UnlockGenericErrorController implements FxController { - - private final Stage window; - private final Lazy unlockScene; - - @Inject - UnlockGenericErrorController(@UnlockWindow Stage window, @FxmlScene(FxmlFile.UNLOCK) Lazy unlockScene) { - this.window = window; - this.unlockScene = unlockScene; - } - - @FXML - public void back() { - window.setScene(unlockScene.get()); - } -} diff --git a/main/ui/src/main/java/org/cryptomator/ui/unlock/UnlockModule.java b/main/ui/src/main/java/org/cryptomator/ui/unlock/UnlockModule.java index d06c9daed..8cca1c1cc 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/unlock/UnlockModule.java +++ b/main/ui/src/main/java/org/cryptomator/ui/unlock/UnlockModule.java @@ -4,8 +4,6 @@ import dagger.Binds; import dagger.Module; import dagger.Provides; import dagger.multibindings.IntoMap; -import javafx.beans.property.ObjectProperty; -import javafx.beans.property.SimpleObjectProperty; import javafx.scene.Scene; import javafx.scene.image.Image; import javafx.stage.Modality; @@ -16,7 +14,6 @@ import org.cryptomator.ui.common.FxController; import org.cryptomator.ui.common.FxControllerKey; import org.cryptomator.ui.common.FxmlFile; import org.cryptomator.ui.common.FxmlScene; -import org.cryptomator.ui.common.StackTraceController; import org.cryptomator.ui.forgetPassword.ForgetPasswordComponent; import javax.inject.Named; @@ -47,13 +44,6 @@ abstract class UnlockModule { return stage; } - @Provides - @Named("genericErrorCause") - @UnlockScoped - static ObjectProperty provideGenericErrorCause() { - return new SimpleObjectProperty<>(); - } - @Provides @FxmlScene(FxmlFile.UNLOCK) @UnlockScoped @@ -75,15 +65,6 @@ abstract class UnlockModule { return fxmlLoaders.createScene("/fxml/unlock_invalid_mount_point.fxml"); } - - @Provides - @FxmlScene(FxmlFile.UNLOCK_GENERIC_ERROR) - @UnlockScoped - static Scene provideGenericErrorScene(@UnlockWindow FXMLLoaderFactory fxmlLoaders) { - return fxmlLoaders.createScene("/fxml/unlock_generic_error.fxml"); - } - - // ------------------ @Binds @@ -101,17 +82,4 @@ abstract class UnlockModule { @FxControllerKey(UnlockInvalidMountPointController.class) abstract FxController bindUnlockInvalidMountPointController(UnlockInvalidMountPointController controller); - @Binds - @IntoMap - @FxControllerKey(UnlockGenericErrorController.class) - abstract FxController bindUnlockGenericErrorController(UnlockGenericErrorController controller); - - @Provides - @IntoMap - @FxControllerKey(StackTraceController.class) - static FxController provideStackTraceController(@Named("genericErrorCause") ObjectProperty errorCause) { - return new StackTraceController(errorCause.get()); - } - - } diff --git a/main/ui/src/main/resources/fxml/addvault_generic_error.fxml b/main/ui/src/main/resources/fxml/addvault_generic_error.fxml deleted file mode 100644 index 2f89e71c2..000000000 --- a/main/ui/src/main/resources/fxml/addvault_generic_error.fxml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - -