Show stack trace in UI for vaults in error state

This commit is contained in:
Sebastian Stenzel
2020-04-21 12:38:36 +02:00
parent a9a983d7ed
commit 243c74b0cb
10 changed files with 138 additions and 31 deletions
@@ -21,10 +21,11 @@ abstract class ErrorModule {
static FXMLLoaderFactory provideFxmlLoaderFactory(Map<Class<? extends FxController>, Provider<FxController>> factories, DefaultSceneFactory sceneFactory, ResourceBundle resourceBundle) {
return new FXMLLoaderFactory(factories, sceneFactory, resourceBundle);
}
@Provides
@Named("stackTrace")
static String provideStackTrace(Throwable cause) {
// TODO deduplicate VaultDetailUnknownErrorController.java
ByteArrayOutputStream baos = new ByteArrayOutputStream();
cause.printStackTrace(new PrintStream(baos));
return baos.toString(StandardCharsets.UTF_8);
@@ -6,13 +6,9 @@ import dagger.Provides;
import dagger.multibindings.IntoMap;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyCodeCombination;
import javafx.scene.input.KeyCombination;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import org.cryptomator.ui.addvaultwizard.AddVaultWizardComponent;
import org.cryptomator.ui.common.DefaultSceneFactory;
import org.cryptomator.ui.common.FXMLLoaderFactory;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.common.FxControllerKey;
@@ -87,7 +83,7 @@ abstract class MainWindowModule {
@IntoMap
@FxControllerKey(VaultDetailController.class)
abstract FxController bindVaultDetailController(VaultDetailController controller);
@Binds
@IntoMap
@FxControllerKey(WelcomeController.class)
@@ -102,7 +98,7 @@ abstract class MainWindowModule {
@IntoMap
@FxControllerKey(VaultDetailUnlockedController.class)
abstract FxController bindVaultDetailUnlockedController(VaultDetailUnlockedController controller);
@Binds
@IntoMap
@FxControllerKey(VaultDetailMissingVaultController.class)
@@ -113,11 +109,15 @@ abstract class MainWindowModule {
@FxControllerKey(VaultDetailNeedsMigrationController.class)
abstract FxController bindVaultDetailNeedsMigrationController(VaultDetailNeedsMigrationController controller);
@Binds
@IntoMap
@FxControllerKey(VaultDetailUnknownErrorController.class)
abstract FxController bindVaultDetailUnknownErrorController(VaultDetailUnknownErrorController controller);
@Binds
@IntoMap
@FxControllerKey(VaultListCellController.class)
abstract FxController bindVaultListCellController(VaultListCellController controller);
}
@@ -0,0 +1,40 @@
package org.cryptomator.ui.mainwindow;
import javafx.beans.binding.Binding;
import javafx.beans.property.ObjectProperty;
import org.cryptomator.common.vaults.Vault;
import org.cryptomator.ui.common.FxController;
import org.fxmisc.easybind.EasyBind;
import javax.inject.Inject;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.nio.charset.StandardCharsets;
@MainWindowScoped
public class VaultDetailUnknownErrorController implements FxController {
private final Binding<String> stackTrace;
@Inject
public VaultDetailUnknownErrorController(ObjectProperty<Vault> vault) {
this.stackTrace = EasyBind.select(vault).selectObject(Vault::lastKnownExceptionProperty).map(this::provideStackTrace).orElse("");
}
private String provideStackTrace(Throwable cause) {
// TODO deduplicate ErrorModule.java
ByteArrayOutputStream baos = new ByteArrayOutputStream();
cause.printStackTrace(new PrintStream(baos));
return baos.toString(StandardCharsets.UTF_8);
}
/* Getter/Setter */
public Binding<String> stackTraceProperty() {
return stackTrace;
}
public String getStackTrace() {
return stackTrace.getValue();
}
}
@@ -18,6 +18,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import java.io.IOException;
@MainWindowScoped
public class VaultListController implements FxController {
@@ -68,8 +69,14 @@ public class VaultListController implements FxController {
case LOCKED:
case NEEDS_MIGRATION:
case MISSING:
VaultState determinedState = VaultListManager.determineVaultState(newValue.getPath());
newValue.setState(determinedState);
try {
VaultState determinedState = VaultListManager.determineVaultState(newValue.getPath());
newValue.setState(determinedState);
} catch (IOException e) {
LOG.warn("Failed to determine vault state for " + newValue.getPath(), e);
newValue.setState(VaultState.ERROR);
newValue.setLastKnownException(e);
}
break;
case ERROR:
case UNLOCKED:
@@ -52,5 +52,6 @@
<fx:include VBox.vgrow="ALWAYS" source="vault_detail_unlocked.fxml" visible="${controller.vault.unlocked}" managed="${controller.vault.unlocked}"/>
<fx:include VBox.vgrow="ALWAYS" source="vault_detail_missing.fxml" visible="${controller.vault.missing}" managed="${controller.vault.missing}"/>
<fx:include VBox.vgrow="ALWAYS" source="vault_detail_needsmigration.fxml" visible="${controller.vault.needsMigration}" managed="${controller.vault.needsMigration}"/>
<fx:include VBox.vgrow="ALWAYS" source="vault_detail_unknownerror.fxml" visible="${controller.vault.unknownError}" managed="${controller.vault.unknownError}"/>
</children>
</VBox>
@@ -0,0 +1,15 @@
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.layout.VBox?>
<VBox xmlns="http://javafx.com/javafx"
xmlns:fx="http://javafx.com/fxml"
fx:controller="org.cryptomator.ui.mainwindow.VaultDetailUnknownErrorController"
alignment="CENTER"
spacing="24">
<children>
<Label text="%generic.error.title" wrapText="true"/>
<Label text="%generic.error.instruction" wrapText="true"/>
<TextArea VBox.vgrow="ALWAYS" text="${controller.stackTrace}" prefRowCount="5" editable="false"/>
</children>
</VBox>