Custom mount point now selected via DirectoryChooser. Fixes #762

This commit is contained in:
Sebastian Stenzel
2019-02-08 12:32:00 +01:00
parent 98cab7e4d8
commit 492e986608
2 changed files with 56 additions and 52 deletions

View File

@@ -26,8 +26,12 @@ import javafx.scene.control.Label;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.text.Text;
import javafx.stage.DirectoryChooser;
import javafx.stage.Stage;
import javafx.util.StringConverter;
import org.apache.commons.lang3.CharUtils;
import org.apache.commons.lang3.SystemUtils;
@@ -50,6 +54,8 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import javax.inject.Named;
import java.io.File;
import java.nio.file.DirectoryNotEmptyException;
import java.nio.file.NotDirectoryException;
import java.util.Arrays;
@@ -68,6 +74,7 @@ public class UnlockController implements ViewController {
.precomputed();
private final Application app;
private final Stage mainWindow;
private final Localization localization;
private final WindowsDriveLetters driveLetters;
private final ChangeListener<Character> driveLetterChangeListener = this::winDriveLetterDidChange;
@@ -79,8 +86,9 @@ public class UnlockController implements ViewController {
private Subscription vaultSubs = Subscription.EMPTY;
@Inject
public UnlockController(Application app, Localization localization, WindowsDriveLetters driveLetters, Optional<KeychainAccess> keychainAccess, Settings settings, ExecutorService executor) {
public UnlockController(Application app, @Named("mainWindow") Stage mainWindow, Localization localization, WindowsDriveLetters driveLetters, Optional<KeychainAccess> keychainAccess, Settings settings, ExecutorService executor) {
this.app = app;
this.mainWindow = mainWindow;
this.localization = localization;
this.driveLetters = driveLetters;
this.keychainAccess = keychainAccess;
@@ -116,13 +124,13 @@ public class UnlockController implements ViewController {
private ChoiceBox<Character> winDriveLetter;
@FXML
private CheckBox useCustomMountPath;
private CheckBox useCustomMountPoint;
@FXML
private Label customMountPathLabel;
private HBox customMountPoint;
@FXML
private TextField customMountPathField;
private Label customMountPointField;
@FXML
private ProgressIndicator progressIndicator;
@@ -151,11 +159,8 @@ public class UnlockController implements ViewController {
savePassword.setDisable(!keychainAccess.isPresent());
unlockAfterStartup.disableProperty().bind(savePassword.disabledProperty().or(savePassword.selectedProperty().not()));
customMountPathLabel.visibleProperty().bind(useCustomMountPath.selectedProperty());
customMountPathLabel.managedProperty().bind(useCustomMountPath.selectedProperty());
customMountPathField.visibleProperty().bind(useCustomMountPath.selectedProperty());
customMountPathField.managedProperty().bind(useCustomMountPath.selectedProperty());
customMountPathField.textProperty().addListener(this::mountPathDidChange);
customMountPoint.visibleProperty().bind(useCustomMountPoint.selectedProperty());
customMountPoint.managedProperty().bind(useCustomMountPoint.selectedProperty());
winDriveLetter.setConverter(new WinDriveLetterLabelConverter());
if (!SystemUtils.IS_OS_WINDOWS) {
@@ -166,16 +171,17 @@ public class UnlockController implements ViewController {
}
if (VolumeImpl.WEBDAV.equals(settings.preferredVolumeImpl().get())) {
useCustomMountPath.setVisible(false);
useCustomMountPath.setManaged(false);
customMountPathField.setMouseTransparent(true);
useCustomMountPoint.setVisible(false);
useCustomMountPoint.setManaged(false);
customMountPoint.setVisible(false);
customMountPoint.setManaged(false);
} else {
useCustomMountPath.setVisible(true);
useCustomMountPoint.setVisible(true);
if (SystemUtils.IS_OS_WINDOWS) {
winDriveLetter.visibleProperty().bind(useCustomMountPath.selectedProperty().not());
winDriveLetter.managedProperty().bind(useCustomMountPath.selectedProperty().not());
winDriveLetterLabel.visibleProperty().bind(useCustomMountPath.selectedProperty().not());
winDriveLetterLabel.managedProperty().bind(useCustomMountPath.selectedProperty().not());
winDriveLetter.visibleProperty().bind(useCustomMountPoint.selectedProperty().not());
winDriveLetter.managedProperty().bind(useCustomMountPoint.selectedProperty().not());
winDriveLetterLabel.visibleProperty().bind(useCustomMountPoint.selectedProperty().not());
winDriveLetterLabel.managedProperty().bind(useCustomMountPoint.selectedProperty().not());
}
}
}
@@ -236,13 +242,13 @@ public class UnlockController implements ViewController {
revealAfterMount.setSelected(vaultSettings.revealAfterMount().get());
if (!settings.preferredVolumeImpl().get().equals(VolumeImpl.WEBDAV)) {
useCustomMountPath.setSelected(vaultSettings.usesIndividualMountPath().get());
customMountPathField.textProperty().setValue(vaultSettings.individualMountPath().getValueSafe());
useCustomMountPoint.setSelected(vaultSettings.usesIndividualMountPath().get());
customMountPointField.textProperty().setValue(vaultSettings.individualMountPath().getValueSafe());
}
vaultSubs = vaultSubs.and(EasyBind.subscribe(unlockAfterStartup.selectedProperty(), vaultSettings.unlockAfterStartup()::set));
vaultSubs = vaultSubs.and(EasyBind.subscribe(revealAfterMount.selectedProperty(), vaultSettings.revealAfterMount()::set));
vaultSubs = vaultSubs.and(EasyBind.subscribe(useCustomMountPath.selectedProperty(), vaultSettings.usesIndividualMountPath()::set));
vaultSubs = vaultSubs.and(EasyBind.subscribe(useCustomMountPoint.selectedProperty(), vaultSettings.usesIndividualMountPath()::set));
}
@@ -285,8 +291,13 @@ public class UnlockController implements ViewController {
}
}
private void mountPathDidChange(ObservableValue<? extends String> property, String oldValue, String newValue) {
vault.setCustomMountPath(newValue);
public void didClickChooseCustomMountPoint(ActionEvent actionEvent) {
DirectoryChooser dirChooser = new DirectoryChooser();
File file = dirChooser.showDialog(mainWindow);
if (file != null) {
customMountPointField.setText(file.toString());
vault.setCustomMountPath(file.toString());
}
}
/**
@@ -299,7 +310,7 @@ public class UnlockController implements ViewController {
if (letter == null) {
return localization.getString("unlock.choicebox.winDriveLetter.auto");
} else {
return Character.toString(letter) + ":";
return letter + ":";
}
}
@@ -417,20 +428,17 @@ public class UnlockController implements ViewController {
} else if (e.getDetectedVersion() == Integer.MAX_VALUE) {
messageText.setText(localization.getString("unlock.errorMessage.unauthenticVersionMac"));
}
}).onError(ServerLifecycleException.class, e -> {
LOG.error("Unlock failed for technical reasons.", e);
messageText.setText(localization.getString("unlock.errorMessage.unlockFailed"));
}).onError(NotDirectoryException.class, e -> {
LOG.error("Mount point not a directory.", e);
LOG.error("Unlock failed. Mount point not a directory: {}", e.getMessage());
advancedOptions.setVisible(true);
customMountPathField.setStyle("-fx-border-color: red;");
messageText.setText(null);
showUnlockFailedErrorDialog("unlock.failedDialog.content.mountPathNonExisting");
}).onError(DirectoryNotEmptyException.class, e -> {
LOG.error("Mount point not empty.", e);
LOG.error("Unlock failed. Mount point not empty: {}", e.getMessage());
advancedOptions.setVisible(true);
customMountPathField.setStyle("-fx-border-color: red;");
messageText.setText(null);
showUnlockFailedErrorDialog("unlock.failedDialog.content.mountPathNotEmpty");
}).onError(Exception.class, e -> {
}).onError(Exception.class, e -> { // including RuntimeExceptions
LOG.error("Unlock failed for technical reasons.", e);
messageText.setText(localization.getString("unlock.errorMessage.unlockFailed"));
}).andFinally(() -> {
@@ -439,9 +447,6 @@ public class UnlockController implements ViewController {
}
advancedOptions.setDisable(false);
progressIndicator.setVisible(false);
if (advancedOptions.isVisible()) { //dirty programming, but otherwise the focus is wrong
customMountPathField.requestFocus();
}
}).runOnce(executor);
}

View File

@@ -7,23 +7,20 @@
Contributors:
Sebastian Stenzel - initial API and implementation
-->
<?import org.cryptomator.ui.controls.SecPasswordField?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.CheckBox?>
<?import javafx.scene.control.ChoiceBox?>
<?import javafx.scene.control.Hyperlink?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.ProgressIndicator?>
<?import javafx.scene.control.CheckBox?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.text.TextFlow?>
<?import javafx.scene.control.Hyperlink?>
<?import javafx.scene.text.Text?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.control.Separator?>
<?import javafx.scene.control.ChoiceBox?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.Text?>
<?import javafx.scene.text.TextFlow?>
<?import org.cryptomator.ui.controls.SecPasswordField?>
<GridPane fx:controller="org.cryptomator.ui.controllers.UnlockController" fx:id="root" vgap="12.0" hgap="12.0" prefWidth="400.0" xmlns:fx="http://javafx.com/fxml" cacheShape="true" cache="true">
<padding>
<Insets top="24.0" right="12.0" bottom="24.0" left="12.0" />
@@ -83,16 +80,18 @@
<CheckBox GridPane.rowIndex="4" GridPane.columnIndex="0" GridPane.columnSpan="2" fx:id="revealAfterMount" text="%unlock.label.revealAfterMount" cacheShape="true" cache="true" />
<!-- Row 3.5 -->
<CheckBox GridPane.rowIndex="5" GridPane.columnIndex="0" GridPane.columnSpan="2" fx:id="useCustomMountPath" text="%unlock.label.useOwnMountPath" cacheShape="true" cache="true" />
<CheckBox GridPane.rowIndex="5" GridPane.columnIndex="0" GridPane.columnSpan="2" fx:id="useCustomMountPoint" text="%unlock.label.useOwnMountPath" cacheShape="true" cache="true" />
<!-- Row 3.6 Alt1 -->
<Label GridPane.rowIndex="6" GridPane.columnIndex="0" fx:id="winDriveLetterLabel" text="%unlock.label.winDriveLetter" cacheShape="true" cache="true" />
<ChoiceBox GridPane.rowIndex="6" GridPane.columnIndex="1" fx:id="winDriveLetter" GridPane.hgrow="ALWAYS" maxWidth="Infinity" cacheShape="true" cache="true" />
<!-- Row 3.6 Alt2 -->
<Label GridPane.rowIndex="6" GridPane.columnIndex="0" fx:id="customMountPathLabel" text="%unlock.label.mountPath" cacheShape="true" cache="true" />
<TextField GridPane.rowIndex="6" GridPane.columnIndex="1" fx:id="customMountPathField" GridPane.hgrow="ALWAYS" maxWidth="Infinity" cacheShape="true" cache="true" />
<HBox fx:id="customMountPoint" GridPane.rowIndex="6" GridPane.columnIndex="0" GridPane.columnSpan="2" spacing="6">
<Label HBox.hgrow="NEVER" minWidth="-Infinity" text="%unlock.label.mountPath" cacheShape="true" cache="true" />
<Label HBox.hgrow="ALWAYS" fx:id="customMountPointField" textOverrun="LEADING_ELLIPSIS" cacheShape="true" cache="true" />
<Button HBox.hgrow="NEVER" minWidth="-Infinity" text="&#xf434;" styleClass="ionicons" onAction="#didClickChooseCustomMountPoint" focusTraversable="true" cacheShape="true" cache="true"/>
</HBox>
</GridPane>
<!-- Row 4 -->