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 index 6a50ee44a..285270b4c 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/common/ErrorComponent.java +++ b/main/ui/src/main/java/org/cryptomator/ui/common/ErrorComponent.java @@ -4,6 +4,7 @@ import dagger.BindsInstance; import dagger.Subcomponent; import javax.annotation.Nullable; +import javafx.application.Platform; import javafx.scene.Scene; import javafx.stage.Stage; @@ -16,6 +17,14 @@ public interface ErrorComponent { Scene scene(); default void showErrorScene() { + if (Platform.isFxApplicationThread()) { + show(); + } else { + Platform.runLater(this::show); + } + } + + private void show() { Stage stage = window(); stage.setScene(scene()); stage.show(); diff --git a/main/ui/src/main/java/org/cryptomator/ui/preferences/GeneralPreferencesController.java b/main/ui/src/main/java/org/cryptomator/ui/preferences/GeneralPreferencesController.java index 208605f51..496ada2ce 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/preferences/GeneralPreferencesController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/preferences/GeneralPreferencesController.java @@ -6,6 +6,7 @@ import org.cryptomator.common.settings.KeychainBackend; import org.cryptomator.common.settings.Settings; import org.cryptomator.common.settings.UiTheme; import org.cryptomator.integrations.keychain.KeychainAccessProvider; +import org.cryptomator.ui.common.ErrorComponent; import org.cryptomator.ui.common.FxController; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -24,6 +25,7 @@ import javafx.scene.control.ChoiceBox; import javafx.scene.control.RadioButton; import javafx.scene.control.Toggle; import javafx.scene.control.ToggleGroup; +import javafx.stage.Stage; import javafx.util.StringConverter; import java.util.Arrays; import java.util.Optional; @@ -37,6 +39,7 @@ public class GeneralPreferencesController implements FxController { private static final Logger LOG = LoggerFactory.getLogger(GeneralPreferencesController.class); + private final Stage window; private final Settings settings; private final boolean trayMenuSupported; private final Optional autoStartStrategy; @@ -47,6 +50,7 @@ public class GeneralPreferencesController implements FxController { private final Application application; private final Environment environment; private final Set keychainAccessProviders; + private final ErrorComponent.Builder errorComponent; public ChoiceBox themeChoiceBox; public ChoiceBox keychainBackendChoiceBox; public CheckBox startHiddenCheckbox; @@ -57,7 +61,8 @@ public class GeneralPreferencesController implements FxController { public RadioButton nodeOrientationRtl; @Inject - GeneralPreferencesController(Settings settings, @Named("trayMenuSupported") boolean trayMenuSupported, Optional autoStartStrategy, Set keychainAccessProviders, ObjectProperty selectedTabProperty, LicenseHolder licenseHolder, ExecutorService executor, ResourceBundle resourceBundle, Application application, Environment environment) { + GeneralPreferencesController(@PreferencesWindow Stage window, Settings settings, @Named("trayMenuSupported") boolean trayMenuSupported, Optional autoStartStrategy, Set keychainAccessProviders, ObjectProperty selectedTabProperty, LicenseHolder licenseHolder, ExecutorService executor, ResourceBundle resourceBundle, Application application, Environment environment, ErrorComponent.Builder errorComponent) { + this.window = window; this.settings = settings; this.trayMenuSupported = trayMenuSupported; this.autoStartStrategy = autoStartStrategy; @@ -68,6 +73,7 @@ public class GeneralPreferencesController implements FxController { this.resourceBundle = resourceBundle; this.application = application; this.environment = environment; + this.errorComponent = errorComponent; } @FXML @@ -129,6 +135,7 @@ public class GeneralPreferencesController implements FxController { toggleTask.setOnFailed(event -> { autoStartCheckbox.setSelected(!enableAutoStart); // restore previous state LOG.error("Failed to toggle autostart.", event.getSource().getException()); + errorComponent.cause(event.getSource().getException()).window(window).returnToScene(window.getScene()).build().showErrorScene(); }); executor.execute(toggleTask); }); 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 de756d899..902f2cd50 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 @@ -4,6 +4,7 @@ import dagger.Lazy; import org.cryptomator.common.vaults.Vault; import org.cryptomator.cryptolib.api.InvalidPassphraseException; 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; @@ -31,16 +32,18 @@ public class RecoveryKeyCreationController implements FxController { private final ExecutorService executor; private final RecoveryKeyFactory recoveryKeyFactory; private final StringProperty recoveryKeyProperty; + private final ErrorComponent.Builder errorComponent; public NiceSecurePasswordField passwordField; @Inject - public RecoveryKeyCreationController(@RecoveryKeyWindow Stage window, @FxmlScene(FxmlFile.RECOVERYKEY_SUCCESS) Lazy successScene, @RecoveryKeyWindow Vault vault, RecoveryKeyFactory recoveryKeyFactory, ExecutorService executor, @RecoveryKeyWindow StringProperty recoveryKey) { + public RecoveryKeyCreationController(@RecoveryKeyWindow Stage window, @FxmlScene(FxmlFile.RECOVERYKEY_SUCCESS) Lazy successScene, @RecoveryKeyWindow Vault vault, RecoveryKeyFactory recoveryKeyFactory, ExecutorService executor, @RecoveryKeyWindow StringProperty recoveryKey, ErrorComponent.Builder errorComponent) { this.window = window; this.successScene = successScene; this.vault = vault; this.executor = executor; this.recoveryKeyFactory = recoveryKeyFactory; this.recoveryKeyProperty = recoveryKey; + this.errorComponent = errorComponent; } @FXML @@ -59,6 +62,7 @@ public class RecoveryKeyCreationController implements FxController { Animations.createShakeWindowAnimation(window).play(); } else { LOG.error("Creation of recovery key failed.", task.getException()); + errorComponent.cause(task.getException()).window(window).returnToScene(window.getScene()).build().showErrorScene(); } }); executor.submit(task); diff --git a/main/ui/src/main/java/org/cryptomator/ui/unlock/UnlockWorkflow.java b/main/ui/src/main/java/org/cryptomator/ui/unlock/UnlockWorkflow.java index 9b95103ad..8cb7e0752 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/unlock/UnlockWorkflow.java +++ b/main/ui/src/main/java/org/cryptomator/ui/unlock/UnlockWorkflow.java @@ -209,9 +209,7 @@ public class UnlockWorkflow extends Task { private void handleGenericError(Throwable e) { LOG.error("Unlock failed for technical reasons.", e); - Platform.runLater(() -> { - errorComponent.cause(e).window(window).returnToScene(window.getScene()).build().showErrorScene(); - }); + errorComponent.cause(e).window(window).returnToScene(window.getScene()).build().showErrorScene(); } private void wipePassword(char[] pw) {