split up check view:

- checkListController is responsible for selecting and (batch)running checks
- checkDetailController is responsible for displaying results
This commit is contained in:
Sebastian Stenzel
2021-05-07 15:51:47 +02:00
parent ac289cc3f7
commit 64d54133f8
13 changed files with 251 additions and 274 deletions

View File

@@ -25,7 +25,7 @@
<project.jdk.version>16</project.jdk.version>
<!-- cryptomator dependencies -->
<cryptomator.cryptofs.version>2.1.0-beta4</cryptomator.cryptofs.version>
<cryptomator.cryptofs.version>2.1.0-beta5</cryptomator.cryptofs.version>
<cryptomator.integrations.version>1.0.0-beta2</cryptomator.integrations.version>
<cryptomator.integrations.win.version>1.0.0-beta2</cryptomator.integrations.win.version>
<cryptomator.integrations.mac.version>1.0.0-beta2</cryptomator.integrations.mac.version>

View File

@@ -12,7 +12,7 @@ public enum FxmlFile {
ERROR("/fxml/error.fxml"), //
FORGET_PASSWORD("/fxml/forget_password.fxml"), //
HEALTH_START("/fxml/health_start.fxml"), //
HEALTH_CHECK("/fxml/health_check.fxml"), //
HEALTH_CHECK("/fxml/health_check_list.fxml"), //
LOCK_FORCED("/fxml/lock_forced.fxml"), //
LOCK_FAILED("/fxml/lock_failed.fxml"), //
MAIN_WINDOW("/fxml/main_window.fxml"), //

View File

@@ -0,0 +1,36 @@
package org.cryptomator.ui.health;
import com.google.common.base.Preconditions;
import com.google.common.base.Suppliers;
import dagger.Lazy;
import javax.inject.Inject;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
import java.util.Collection;
import java.util.Iterator;
import java.util.concurrent.ExecutorService;
import java.util.function.Supplier;
public class BatchService extends Service<Void> {
private final Iterator<HealthCheckTask> remainingTasks;
@Inject
public BatchService(Iterable<HealthCheckTask> tasks) {
this.remainingTasks = tasks.iterator();
}
@Override
protected Task<Void> createTask() {
Preconditions.checkState(remainingTasks.hasNext(), "No remaining tasks");
return remainingTasks.next();
}
@Override
protected void succeeded() {
if (remainingTasks.hasNext()) {
this.restart();
}
}
}

View File

@@ -8,99 +8,56 @@ import org.cryptomator.ui.common.FxController;
import javax.inject.Inject;
import javafx.beans.binding.Binding;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.ReadOnlyBooleanProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.concurrent.Worker;
import javafx.fxml.FXML;
import javafx.scene.control.ListView;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import java.util.concurrent.ExecutorService;
@HealthCheckScoped
public class CheckController implements FxController {
public class CheckDetailController implements FxController {
private final HealthCheckSupervisor supervisor;
private final HealthReportWriteTask reportWriter;
private final ExecutorService executorService;
private final ObjectProperty<HealthCheckTask> selectedTask;
private final Binding<ObservableList<DiagnosticResult>> selectedResults;
private final OptionalBinding<Worker.State> selectedTaskState;
private final Binding<String> selectedTaskName;
private final Binding<String> selectedTaskDescription;
private final ReadOnlyBooleanProperty running;
/* FXML */
public ListView<HealthCheckTask> checksListView;
public TableView<DiagnosticResult> resultsTableView;
public TableColumn<DiagnosticResult, String> resultDescriptionColumn;
public TableColumn<DiagnosticResult, String> resultSeverityColumn;
@Inject
public CheckController(HealthCheckSupervisor supervisor, HealthReportWriteTask reportWriteTask, ExecutorService executorService) {
this.supervisor = supervisor;
this.reportWriter = reportWriteTask;
this.executorService = executorService;
this.selectedTask = new SimpleObjectProperty<>();
public CheckDetailController(ObjectProperty<HealthCheckTask> selectedTask) {
this.selectedResults = EasyBind.wrapNullable(selectedTask).map(HealthCheckTask::results).orElse(FXCollections.emptyObservableList());
this.selectedTaskState = EasyBind.wrapNullable(selectedTask).mapObservable(HealthCheckTask::stateProperty);
this.selectedTaskName = EasyBind.wrapNullable(selectedTask).map(HealthCheckTask::getTitle).orElse("");
this.selectedTaskDescription = EasyBind.wrapNullable(selectedTask).map(task -> task.getCheck().toString()).orElse("");
this.running = supervisor.runningProperty();
}
@FXML
public void initialize() {
checksListView.setItems(FXCollections.observableArrayList(supervisor.getTasks()));
checksListView.setCellFactory(ignored -> new CheckListCell());
checksListView.getSelectionModel().select(0);
selectedTask.bind(checksListView.getSelectionModel().selectedItemProperty());
resultsTableView.itemsProperty().bind(selectedResults);
resultDescriptionColumn.setCellValueFactory(cellFeatures -> new SimpleStringProperty(cellFeatures.getValue().toString()));
resultSeverityColumn.setCellValueFactory(cellFeatures -> new SimpleStringProperty(cellFeatures.getValue().getServerity().name()));
executorService.execute(supervisor);
}
@FXML
public void cancelCheck() {
assert running.get();
supervisor.cancel(true);
}
/* Getter/Setter */
@FXML
public void exportResults() {
executorService.execute(reportWriter);
}
/* Getter&Setter */
public boolean isRunning() {
return running.get();
}
public ReadOnlyBooleanProperty runningProperty() {
return running;
public String getSelectedTaskName() {
return selectedTaskName.getValue();
}
public Binding<String> selectedTaskNameProperty() {
return selectedTaskName;
}
public String isSelectedTaskName() {
return selectedTaskName.getValue();
public String getSelectedTaskDescription() {
return selectedTaskDescription.getValue();
}
public Binding<String> selectedTaskDescriptionProperty() {
return selectedTaskDescription;
}
public String isSelectedTaskDescription() {
return selectedTaskDescription.getValue();
}
}

View File

@@ -0,0 +1,105 @@
package org.cryptomator.ui.health;
import com.google.common.base.Preconditions;
import com.tobiasdiez.easybind.EasyBind;
import com.tobiasdiez.easybind.optional.OptionalBinding;
import dagger.Lazy;
import org.cryptomator.cryptofs.health.api.DiagnosticResult;
import org.cryptomator.ui.common.FxController;
import javax.inject.Inject;
import javafx.beans.binding.Binding;
import javafx.beans.binding.BooleanBinding;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.concurrent.Worker;
import javafx.fxml.FXML;
import javafx.scene.control.ListView;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import java.util.Collection;
import java.util.concurrent.ExecutorService;
@HealthCheckScoped
public class CheckListController implements FxController {
private final ObservableList<HealthCheckTask> tasks;
private final HealthReportWriteTask reportWriter;
private final ExecutorService executorService;
private final ObjectProperty<HealthCheckTask> selectedTask;
private final SimpleObjectProperty<Worker<?>> runningTask;
private final Binding<Boolean> running;
private final BooleanBinding anyCheckSelected;
/* FXML */
public ListView<HealthCheckTask> checksListView;
@Inject
public CheckListController(Lazy<Collection<HealthCheckTask>> tasks, HealthReportWriteTask reportWriteTask, ObjectProperty<HealthCheckTask> selectedTask, ExecutorService executorService) {
this.tasks = FXCollections.observableArrayList(tasks.get());
this.reportWriter = reportWriteTask;
this.executorService = executorService;
this.selectedTask = selectedTask;
this.runningTask = new SimpleObjectProperty<>();
this.running = EasyBind.wrapNullable(runningTask).map(Worker::isRunning).orElse(false);
this.anyCheckSelected = selectedTask.isNotNull();
}
@FXML
public void initialize() {
checksListView.setItems(tasks);
checksListView.setCellFactory(ignored -> new CheckListCell());
selectedTask.bind(checksListView.getSelectionModel().selectedItemProperty());
}
@FXML
public synchronized void runSelectedChecks() {
Preconditions.checkState(runningTask.get() == null);
var batch = new BatchService(checksListView.getSelectionModel().getSelectedItems());
batch.setExecutor(executorService);
batch.start();
runningTask.set(batch);
}
@FXML
public synchronized void runAllChecks() {
Preconditions.checkState(runningTask.get() == null);
var batch = new BatchService(checksListView.getItems());
batch.setExecutor(executorService);
batch.start();
runningTask.set(batch);
}
@FXML
public synchronized void cancelCheck() {
Preconditions.checkState(runningTask.get() != null);
runningTask.get().cancel();
}
@FXML
public void exportResults() {
executorService.execute(reportWriter);
}
/* Getter/Setter */
public boolean isRunning() {
return running.getValue();
}
public Binding<Boolean> runningProperty() {
return running;
}
public boolean isAnyCheckSelected() {
return anyCheckSelected.get();
}
public BooleanBinding anyCheckSelectedProperty() {
return anyCheckSelected;
}
}

View File

@@ -20,11 +20,13 @@ import org.cryptomator.ui.keyloading.KeyLoadingStrategy;
import org.cryptomator.ui.mainwindow.MainWindow;
import javax.inject.Provider;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ChangeListener;
import javafx.scene.Scene;
import javafx.stage.Modality;
import javafx.stage.Stage;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
import java.util.Optional;
@@ -40,12 +42,6 @@ abstract class HealthCheckModule {
return new AtomicReference<>();
}
@Provides
@HealthCheckScoped
static Runnable provideMasterkeyDestructor(AtomicReference<Masterkey> masterkeyRef) {
return () -> Optional.ofNullable(masterkeyRef.getAndSet(null)).ifPresent(Masterkey::destroy);
}
@Provides
@HealthCheckScoped
static AtomicReference<VaultConfig> provideVaultConfigRef() {
@@ -54,15 +50,21 @@ abstract class HealthCheckModule {
@Provides
@HealthCheckScoped
static Collection<HealthCheck> provideSelectedHealthChecks() {
return new ArrayList<>();
static Collection<HealthCheck> provideAvailableHealthChecks() {
return HealthCheck.allChecks();
}
@Provides
@HealthCheckScoped
static ObjectProperty<HealthCheckTask> provideSelectedHealthCheckTask() {
return new SimpleObjectProperty<>();
}
/* Only inject with Lazy-Wrapper!*/
@Provides
@HealthCheckScoped
static Collection<HealthCheckTask> provideSelectedHealthCheckTasks(Collection<HealthCheck> selectedHealthChecks, @HealthCheckWindow Vault vault, AtomicReference<Masterkey> masterkeyRef, AtomicReference<VaultConfig> vaultConfigRef, SecureRandom csprng) {
return selectedHealthChecks.stream().map(check -> new HealthCheckTask(vault.getPath(), vaultConfigRef.get(), masterkeyRef.get(), csprng, check)).toList();
static Collection<HealthCheckTask> provideAvailableHealthCheckTasks(Collection<HealthCheck> availableHealthChecks, @HealthCheckWindow Vault vault, AtomicReference<Masterkey> masterkeyRef, AtomicReference<VaultConfig> vaultConfigRef, SecureRandom csprng) {
return availableHealthChecks.stream().map(check -> new HealthCheckTask(vault.getPath(), vaultConfigRef.get(), masterkeyRef.get(), csprng, check)).toList();
}
@Provides
@@ -82,20 +84,26 @@ abstract class HealthCheckModule {
@Provides
@HealthCheckWindow
@HealthCheckScoped
static Stage provideStage(StageFactory factory, @MainWindow Stage owner, ResourceBundle resourceBundle, Runnable masterkeyDestructor) {
static Stage provideStage(StageFactory factory, @MainWindow Stage owner, ResourceBundle resourceBundle, ChangeListener<Boolean> showingListener) {
Stage stage = factory.create();
stage.setTitle(resourceBundle.getString("health.title"));
stage.setResizable(true);
stage.initModality(Modality.WINDOW_MODAL);
stage.initOwner(owner);
stage.showingProperty().addListener((observable, wasShowing, isShowing) -> { //TODO: should we use showingProperty or onCloseRequest
if (!isShowing) {
masterkeyDestructor.run();
}
});
stage.showingProperty().addListener(showingListener); // bind masterkey lifecycle to window
return stage;
}
@Provides
@HealthCheckScoped
static ChangeListener<Boolean> provideWindowShowingChangeListener(AtomicReference<Masterkey> masterkey) {
return (observable, wasShowing, isShowing) -> {
if (!isShowing) {
Optional.ofNullable(masterkey.getAndSet(null)).ifPresent(Masterkey::destroy);
}
};
}
@Provides
@FxmlScene(FxmlFile.HEALTH_START)
@HealthCheckScoped
@@ -117,7 +125,13 @@ abstract class HealthCheckModule {
@Binds
@IntoMap
@FxControllerKey(CheckController.class)
abstract FxController bindCheckController(CheckController controller);
@FxControllerKey(CheckListController.class)
abstract FxController bindCheckController(CheckListController controller);
@Binds
@IntoMap
@FxControllerKey(CheckDetailController.class)
abstract FxController bindCheckDetailController(CheckDetailController controller);
}

View File

@@ -1,80 +0,0 @@
package org.cryptomator.ui.health;
import dagger.Lazy;
import javax.inject.Inject;
import javafx.concurrent.Task;
import java.util.Collection;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicReference;
@HealthCheckScoped
public class HealthCheckSupervisor extends Task<Void> {
private final ExecutorService executor;
private final Lazy<Collection<HealthCheckTask>> lazyTasks;
private final Runnable masterkeyDestructor;
private final AtomicReference<HealthCheckTask> currentTask;
private final ConcurrentLinkedQueue<HealthCheckTask> remainingTasks;
@Inject
public HealthCheckSupervisor(Lazy<Collection<HealthCheckTask>> lazyTasks, Runnable masterkeyDestructor) {
this.lazyTasks = lazyTasks;
this.masterkeyDestructor = masterkeyDestructor;
this.currentTask = new AtomicReference<>(null);
this.executor = Executors.newSingleThreadExecutor();
this.remainingTasks = new ConcurrentLinkedQueue<>();
}
public Void call() {
remainingTasks.addAll(lazyTasks.get());
while (!remainingTasks.isEmpty()) {
final var task = remainingTasks.remove();
currentTask.set(task);
executor.execute(task); //TODO: think about if we set the scheduled property for all tasks?
try {
task.get();
} catch (InterruptedException e) {
executor.shutdownNow();
cleanup();
;
Thread.currentThread().interrupt(); //TODO: do we need this?
} catch (ExecutionException e) {
e.printStackTrace();
} catch (CancellationException e) {
// ok
}
}
return null;
}
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
cleanup();
currentTask.get().cancel(mayInterruptIfRunning);
if (mayInterruptIfRunning) {
executor.shutdownNow();
} else {
executor.shutdown();
}
return super.cancel(mayInterruptIfRunning);
}
private void cleanup() {
remainingTasks.forEach(task -> task.cancel(false));
remainingTasks.clear();
}
@Override
protected void done() {
masterkeyDestructor.run(); //TODO: if we destroy it, no check can rerun
}
public Collection<HealthCheckTask> getTasks() {
return lazyTasks.get();
}
}

View File

@@ -44,8 +44,6 @@ public class StartController implements FxController {
private static final Logger LOG = LoggerFactory.getLogger(StartController.class);
private final Stage window;
private final Collection<HealthCheck> availableChecks;
private final Map<HealthCheck, BooleanProperty> availableCheckListSelectProperties;
private final Optional<VaultConfig.UnverifiedVaultConfig> unverifiedVaultConfig;
private final KeyLoadingStrategy keyLoadingStrategy;
private final ExecutorService executor;
@@ -55,11 +53,6 @@ public class StartController implements FxController {
private final Lazy<Scene> checkScene;
/* FXML */
public ListView availableChecksList;
public RadioButton customCheckSetButton;
public RadioButton quickCheckSetButton;
public RadioButton fullCheckSetButton;
public ToggleGroup checksSetToggleGroup;
@Inject
public StartController(@HealthCheckWindow Vault vault, @HealthCheckWindow Stage window, @HealthCheckWindow KeyLoadingStrategy keyLoadingStrategy, ExecutorService executor, AtomicReference<Masterkey> masterkeyRef, AtomicReference<VaultConfig> vaultConfigRef, Collection<HealthCheck> selectedChecks, @FxmlScene(FxmlFile.HEALTH_CHECK) Lazy<Scene> checkScene) {
@@ -71,31 +64,6 @@ public class StartController implements FxController {
this.vaultConfigRef = vaultConfigRef;
this.selectedChecks = selectedChecks;
this.checkScene = checkScene;
this.availableChecks = HealthCheck.allChecks();
this.availableCheckListSelectProperties = new HashMap<>();
availableChecks.forEach(check -> availableCheckListSelectProperties.put(check, new SimpleBooleanProperty(false)));
}
public void initialize() {
availableChecksList.setItems(FXCollections.observableList(availableChecks.stream().toList()));
availableChecksList.setCellFactory(CheckBoxListCell.forListView(availableCheckListSelectProperties::get));
availableChecksList.setEditable(false);
var availableCheckIds = availableChecks.stream().map(HealthCheck::identifier).toList();
if (PredefinedCheckSet.QUICK.getCheckIds().stream().anyMatch(checkId -> !availableCheckIds.contains(checkId))) {
quickCheckSetButton.setVisible(false);
quickCheckSetButton.setManaged(false);
}
if (PredefinedCheckSet.FULL.getCheckIds().stream().anyMatch(checkId -> !availableCheckIds.contains(checkId))) {
fullCheckSetButton.setVisible(false);
fullCheckSetButton.setManaged(false);
}
quickCheckSetButton.setUserData(PredefinedCheckSet.QUICK);
fullCheckSetButton.setUserData(PredefinedCheckSet.FULL);
customCheckSetButton.setUserData(PredefinedCheckSet.CUSTOM);
}
@FXML
@@ -106,15 +74,6 @@ public class StartController implements FxController {
@FXML
public void next() {
switch ((PredefinedCheckSet) checksSetToggleGroup.getSelectedToggle().getUserData()) {
case FULL -> selectedChecks.addAll(availableChecks);
case QUICK -> selectedChecks.addAll(availableChecks.stream().filter(check -> PredefinedCheckSet.QUICK.getCheckIds().contains(check.identifier())).toList());
case CUSTOM -> availableCheckListSelectProperties.forEach((check, selected) -> {
if (selected.get()) {
selectedChecks.add(check);
}
});
}
LOG.trace("StartController.next()");
executor.submit(this::loadKey);
}
@@ -166,27 +125,4 @@ public class StartController implements FxController {
return unverifiedVaultConfig.isEmpty();
}
public BooleanBinding anyCheckSetSelectedProperty() {
return checksSetToggleGroup.selectedToggleProperty().isNotNull();
}
public boolean isAnyCheckSetSelected() {
return anyCheckSetSelectedProperty().get();
}
enum PredefinedCheckSet {
QUICK(DirIdCheck.class.getCanonicalName()), //TODO: get identifier via static method?
FULL(DirIdCheck.class.getCanonicalName()),
CUSTOM();
private Collection<String> checkIds;
PredefinedCheckSet(String... checkIds) {
this.checkIds = Set.of(checkIds);
}
Collection<String> getCheckIds() {
return checkIds;
}
}
}

View File

@@ -1,41 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.ListView?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Text?>
<HBox xmlns:fx="http://javafx.com/fxml"
xmlns="http://javafx.com/javafx"
fx:controller="org.cryptomator.ui.health.CheckController"
minWidth="400"
maxWidth="400"
minHeight="145"
spacing="12">
<padding>
<Insets topRightBottomLeft="12"/>
</padding>
<children>
<VBox minWidth="80">
<Label fx:id="listHeading" text="Health checks"/>
<ListView fx:id="checksListView"/>
<Button text="%generic.button.cancel" onAction="#cancelCheck" disable="${!controller.running}" maxWidth="Infinity"/>
<Button text="Export Results" onAction="#exportResults" disable="${controller.running}" maxWidth="Infinity"/>
</VBox>
<VBox spacing="6">
<Label fx:id="checkTitle" styleClass="label-large" text="${controller.selectedTaskName}" />
<Text fx:id="checkDescription" styleClass="label" text="${controller.selectedTaskDescription}" />
<TableView fx:id="resultsTableView" >
<columns>
<TableColumn fx:id="resultDescriptionColumn" text="Info" editable="false"/>
<TableColumn fx:id="resultSeverityColumn" text="Severity" editable="false"/>
<!--TableColumn fx:id="resultAction" text="Action" /-->
</columns>
</TableView>
</VBox>
</children>
</HBox>

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Text?>
<VBox xmlns:fx="http://javafx.com/fxml"
xmlns="http://javafx.com/javafx"
fx:controller="org.cryptomator.ui.health.CheckDetailController"
spacing="6">
<Label fx:id="checkTitle" styleClass="label-large" text="${controller.selectedTaskName}"/>
<Text fx:id="checkDescription" styleClass="label" text="${controller.selectedTaskDescription}"/>
<!-- TODO hide if state != succeeded: -->
<TableView fx:id="resultsTableView">
<columns>
<TableColumn fx:id="resultDescriptionColumn" text="Info" editable="false"/>
<TableColumn fx:id="resultSeverityColumn" text="Severity" editable="false"/>
<!--TableColumn fx:id="resultAction" text="Action" /-->
</columns>
</TableView>
</VBox>

View File

@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ButtonBar?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.ListView?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<VBox xmlns:fx="http://javafx.com/fxml"
xmlns="http://javafx.com/javafx"
fx:controller="org.cryptomator.ui.health.CheckListController"
minWidth="400"
maxWidth="400"
minHeight="145"
spacing="12">
<padding>
<Insets topRightBottomLeft="12"/>
</padding>
<children>
<HBox>
<VBox minWidth="80">
<Label fx:id="listHeading" text="Health checks"/>
<ListView fx:id="checksListView"/>
<!-- TODO: clean up button states: -->
<Button text="TODO: run selected" onAction="#runSelectedChecks" disable="${controller.running || !controller.anyCheckSelected}" maxWidth="Infinity"/>
<Button text="TODO: run all" onAction="#runAllChecks" disable="${controller.running}" maxWidth="Infinity"/>
<Button text="%generic.button.cancel" onAction="#cancelCheck" disable="${!controller.running}" maxWidth="Infinity"/>
</VBox>
<fx:include source="/fxml/health_check_details.fxml" visible="${controller.anyCheckSelected}" managed="${controller.anyCheckSelected}"/>
</HBox>
<ButtonBar buttonMinWidth="120" buttonOrder="+X">
<buttons>
<!-- TODO: hide/disable if no results yet -->
<Button text="TODO Export Results" ButtonBar.buttonData="NEXT_FORWARD" disable="${controller.running}" onAction="#exportResults"/>
</buttons>
</ButtonBar>
</children>
</VBox>

View File

@@ -16,29 +16,18 @@
maxWidth="400"
minHeight="145"
spacing="12">
<fx:define>
<ToggleGroup fx:id="checksSetToggleGroup"/>
</fx:define>
<padding>
<Insets topRightBottomLeft="12"/>
</padding>
<children>
<Label text="TODO: Invalid vault config" visible="${controller.invalidConfig}" managed="${controller.invalidConfig}"/>
<Label text="Please select, which check(s) should be performed:"/>
<VBox spacing="6" disable="${controller.invalidConfig}">
<RadioButton fx:id="quickCheckSetButton" toggleGroup="${checksSetToggleGroup}" text="Quick Check"/>
<RadioButton fx:id="fullCheckSetButton" toggleGroup="${checksSetToggleGroup}" text="Full Check"/>
<AnchorPane >
<RadioButton fx:id="customCheckSetButton" toggleGroup="${checksSetToggleGroup}" text="Custom Check"/>
<ListView fx:id="availableChecksList" AnchorPane.leftAnchor="20.0" AnchorPane.topAnchor="20.0" maxHeight="100" visible="${customCheckSetButton.selected}"/>
</AnchorPane>
</VBox>
<Label text="TODO: Blabla going to health check now...:"/>
<ButtonBar buttonMinWidth="120" buttonOrder="+CX">
<buttons>
<Button text="%generic.button.cancel" ButtonBar.buttonData="CANCEL_CLOSE" cancelButton="true" onAction="#close"/>
<Button text="%generic.button.next" ButtonBar.buttonData="NEXT_FORWARD" disable="${controller.invalidConfig || !controller.anyCheckSetSelected}" defaultButton="true" onAction="#next"/>
<Button text="%generic.button.next" ButtonBar.buttonData="NEXT_FORWARD" disable="${controller.invalidConfig}" defaultButton="true" onAction="#next"/>
</buttons>
</ButtonBar>
</children>

View File

@@ -19,10 +19,10 @@ Cryptomator uses 45 third-party dependencies under the following licenses:
- jnr-ffi (com.github.jnr:jnr-ffi:2.1.12 - http://github.com/jnr/jnr-ffi)
- FindBugs-jsr305 (com.google.code.findbugs:jsr305:3.0.2 - http://findbugs.sourceforge.net/)
- Gson (com.google.code.gson:gson:2.8.6 - https://github.com/google/gson/gson)
- Dagger (com.google.dagger:dagger:2.32 - https://github.com/google/dagger)
- error-prone annotations (com.google.errorprone:error_prone_annotations:2.3.4 - http://nexus.sonatype.org/oss-repository-hosting.html/error_prone_parent/error_prone_annotations)
- Dagger (com.google.dagger:dagger:2.35.1 - https://github.com/google/dagger)
- error-prone annotations (com.google.errorprone:error_prone_annotations:2.5.1 - http://nexus.sonatype.org/oss-repository-hosting.html/error_prone_parent/error_prone_annotations)
- Guava InternalFutureFailureAccess and InternalFutures (com.google.guava:failureaccess:1.0.1 - https://github.com/google/guava/failureaccess)
- Guava: Google Core Libraries for Java (com.google.guava:guava:30.1-jre - https://github.com/google/guava/guava)
- Guava: Google Core Libraries for Java (com.google.guava:guava:30.1.1-jre - https://github.com/google/guava/guava)
- Guava ListenableFuture only (com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava - https://github.com/google/guava/listenablefuture)
- J2ObjC Annotations (com.google.j2objc:j2objc-annotations:1.3 - https://github.com/google/j2objc/)
- Apache Commons CLI (commons-cli:commons-cli:1.4 - http://commons.apache.org/proper/commons-cli/)
@@ -70,11 +70,11 @@ Cryptomator uses 45 third-party dependencies under the following licenses:
- Java Native Access (net.java.dev.jna:jna:5.7.0 - https://github.com/java-native-access/jna)
- Java Native Access Platform (net.java.dev.jna:jna-platform:5.7.0 - https://github.com/java-native-access/jna)
MIT License:
- java jwt (com.auth0:java-jwt:3.13.0 - https://github.com/auth0/java-jwt)
- java jwt (com.auth0:java-jwt:3.15.0 - https://github.com/auth0/java-jwt)
- jnr-x86asm (com.github.jnr:jnr-x86asm:1.0.2 - http://github.com/jnr/jnr-x86asm)
- jnr-fuse (com.github.serceman:jnr-fuse:0.5.5 - https://github.com/SerCeMan/jnr-fuse)
- zxcvbn4j (com.nulab-inc:zxcvbn:1.3.0 - https://github.com/nulab/zxcvbn4j)
- Checker Qual (org.checkerframework:checker-qual:3.5.0 - https://checkerframework.org)
- Checker Qual (org.checkerframework:checker-qual:3.8.0 - https://checkerframework.org)
- SLF4J API Module (org.slf4j:slf4j-api:1.7.30 - http://www.slf4j.org)
The BSD 2-Clause License:
- EasyBind (com.tobiasdiez:easybind:2.1.0 - https://github.com/tobiasdiez/EasyBind)