diff --git a/main/ui/src/main/java/org/cryptomator/ui/controllers/UnlockController.java b/main/ui/src/main/java/org/cryptomator/ui/controllers/UnlockController.java
index 2001e50b6..9584bfc81 100644
--- a/main/ui/src/main/java/org/cryptomator/ui/controllers/UnlockController.java
+++ b/main/ui/src/main/java/org/cryptomator/ui/controllers/UnlockController.java
@@ -9,10 +9,6 @@
package org.cryptomator.ui.controllers;
import javax.inject.Inject;
-import java.nio.file.Files;
-import java.nio.file.InvalidPathException;
-import java.nio.file.Path;
-import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Objects;
@@ -22,7 +18,6 @@ import java.util.concurrent.ExecutorService;
import com.google.common.base.CharMatcher;
import com.google.common.base.Strings;
import javafx.application.Application;
-import javafx.beans.binding.Bindings;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
@@ -39,7 +34,6 @@ import javafx.scene.control.ProgressIndicator;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.GridPane;
-import javafx.scene.layout.HBox;
import javafx.scene.text.Text;
import javafx.util.StringConverter;
import org.apache.commons.lang3.CharUtils;
@@ -51,6 +45,7 @@ import org.cryptomator.cryptolib.api.InvalidPassphraseException;
import org.cryptomator.cryptolib.api.UnsupportedVaultFormatException;
import org.cryptomator.frontend.webdav.ServerLifecycleException;
import org.cryptomator.keychain.KeychainAccess;
+import org.cryptomator.ui.model.InvalidSettingsException;
import org.cryptomator.ui.controls.SecPasswordField;
import org.cryptomator.ui.l10n.Localization;
import org.cryptomator.ui.model.Vault;
@@ -122,18 +117,12 @@ public class UnlockController implements ViewController {
@FXML
private CheckBox useOwnMountPath;
- @FXML
- private HBox mountPathBox;
-
@FXML
private Label mountPathLabel;
@FXML
private TextField mountPath;
- @FXML
- private Button changeMountPathButton;
-
@FXML
private ProgressIndicator progressIndicator;
@@ -161,13 +150,10 @@ public class UnlockController implements ViewController {
savePassword.setDisable(!keychainAccess.isPresent());
unlockAfterStartup.disableProperty().bind(savePassword.disabledProperty().or(savePassword.selectedProperty().not()));
- mountPathLabel.setVisible(false);
- mountPathBox.visibleProperty().bind(mountPathLabel.visibleProperty());
- mountPathBox.managedProperty().bind(mountPathLabel.managedProperty());
- mountPath.visibleProperty().bind(mountPathLabel.visibleProperty());
- mountPath.managedProperty().bind(mountPathLabel.managedProperty());
- changeMountPathButton.visibleProperty().bind(mountPathLabel.visibleProperty());
- changeMountPathButton.managedProperty().bind(mountPathLabel.managedProperty());
+ mountPathLabel.visibleProperty().bind(useOwnMountPath.selectedProperty());
+ mountPath.visibleProperty().bind(useOwnMountPath.selectedProperty());
+ mountPath.managedProperty().bind(useOwnMountPath.selectedProperty());
+ mountPath.textProperty().addListener(this::mountPathDidChange);
if (SystemUtils.IS_OS_WINDOWS) {
winDriveLetter.setConverter(new WinDriveLetterLabelConverter());
@@ -175,7 +161,7 @@ public class UnlockController implements ViewController {
useOwnMountPath.setManaged(false);
mountPathLabel.setManaged(false);
//dirty cheat
- mountPathBox.setMouseTransparent(true);
+ mountPath.setMouseTransparent(true);
} else {
winDriveLetterLabel.setVisible(false);
winDriveLetterLabel.setManaged(false);
@@ -187,10 +173,9 @@ public class UnlockController implements ViewController {
mountPathLabel.setManaged(false);
}
}
- changeMountPathButton.disableProperty().bind(Bindings.createBooleanBinding(this::isDirVaild, mountPath.textProperty()).not());
-
}
+
@Override
public Parent getRoot() {
return root;
@@ -252,11 +237,8 @@ public class UnlockController implements ViewController {
vaultSubs = vaultSubs.and(EasyBind.subscribe(revealAfterMount.selectedProperty(), vaultSettings.revealAfterMount()::set));
vaultSubs = vaultSubs.and(EasyBind.subscribe(useOwnMountPath.selectedProperty(), vaultSettings.usesIndividualMountPath()::set));
- changeMountPathButton.visibleProperty().bind(
- vaultSettings.individualMountPath().isNotEqualTo(mountPath.textProperty())
- );
+
mountPath.textProperty().setValue(vaultSettings.individualMountPath().getValueSafe());
- mountPathLabel.visibleProperty().bind(useOwnMountPath.selectedProperty());
}
@@ -284,28 +266,6 @@ public class UnlockController implements ViewController {
}
}
- @FXML
- private void didClickchangeMountPathButton(ActionEvent event) {
- assert isDirVaild();
- vault.setMountPath(mountPath.getText());
- }
-
- private boolean isDirVaild() {
- try {
- if (!mountPath.textProperty().isEmpty().get()) {
- Path p = Paths.get(mountPath.textProperty().get());
- return Files.isDirectory(p) && Files.isReadable(p) && Files.isWritable(p) && Files.isExecutable(p);
- } else {
- return false;
- }
-
- } catch (InvalidPathException e) {
- LOG.info("Invalid path");
- return false;
- }
- }
-
-
private void filterAlphanumericKeyEvents(KeyEvent t) {
if (!Strings.isNullOrEmpty(t.getCharacter()) && !ALPHA_NUMERIC_MATCHER.matchesAllOf(t.getCharacter())) {
t.consume();
@@ -321,6 +281,10 @@ public class UnlockController implements ViewController {
}
}
+ private void mountPathDidChange(ObservableValue extends String> property, String oldValue, String newValue) {
+ vault.setIndividualMountPath(newValue);
+ }
+
/**
* Converts 'C' to "C:" to translate between model and GUI.
*/
@@ -420,6 +384,7 @@ public class UnlockController implements ViewController {
@FXML
private void didClickUnlockButton(ActionEvent event) {
advancedOptions.setDisable(true);
+ advancedOptions.setVisible(false);
progressIndicator.setVisible(true);
CharSequence password = passwordField.getCharacters();
@@ -432,6 +397,10 @@ public class UnlockController implements ViewController {
messageText.setText(null);
downloadsPageLink.setVisible(false);
listener.ifPresent(lstnr -> lstnr.didUnlock(vault));
+ }).onError(InvalidSettingsException.class, e -> {
+ messageText.setText(localization.getString("unlock.errorMessage.invalidMountPath"));
+ advancedOptions.setVisible(true);
+ mountPath.setStyle("-fx-border-color: red;");
}).onError(InvalidPassphraseException.class, e -> {
messageText.setText(localization.getString("unlock.errorMessage.wrongPassword"));
passwordField.selectAll();
@@ -451,14 +420,17 @@ public class UnlockController implements ViewController {
LOG.error("Unlock failed for technical reasons.", e);
messageText.setText(localization.getString("unlock.errorMessage.unlockFailed"));
}).onError(Exception.class, e -> {
- LOG.error("Unlock failed for technical reasons.", e);
- messageText.setText(localization.getString("unlock.errorMessage.unlockFailed"));
+ LOG.error("Unlock failed for technical reasons.", e);
+ messageText.setText(localization.getString("unlock.errorMessage.unlockFailed"));
}).andFinally(() -> {
if (!savePassword.isSelected()) {
passwordField.swipe();
}
advancedOptions.setDisable(false);
progressIndicator.setVisible(false);
+ if (advancedOptions.isVisible()) { //dirty programming, but otherwise the focus is wrong
+ mountPath.requestFocus();
+ }
}).runOnce(executor);
}
diff --git a/main/ui/src/main/java/org/cryptomator/ui/model/InvalidSettingsException.java b/main/ui/src/main/java/org/cryptomator/ui/model/InvalidSettingsException.java
new file mode 100644
index 000000000..ed9b39040
--- /dev/null
+++ b/main/ui/src/main/java/org/cryptomator/ui/model/InvalidSettingsException.java
@@ -0,0 +1,5 @@
+package org.cryptomator.ui.model;
+
+public class InvalidSettingsException extends RuntimeException {
+
+}
diff --git a/main/ui/src/main/java/org/cryptomator/ui/model/Vault.java b/main/ui/src/main/java/org/cryptomator/ui/model/Vault.java
index f54f6d337..cf0e6d7cc 100644
--- a/main/ui/src/main/java/org/cryptomator/ui/model/Vault.java
+++ b/main/ui/src/main/java/org/cryptomator/ui/model/Vault.java
@@ -98,9 +98,12 @@ public class Vault {
CryptoFileSystemProvider.changePassphrase(getPath(), MASTERKEY_FILENAME, oldPassphrase, newPassphrase);
}
- public synchronized void unlock(CharSequence passphrase) throws CryptoException, IOException, Volume.VolumeException {
+ public synchronized void unlock(CharSequence passphrase) throws InvalidSettingsException, CryptoException, IOException, Volume.VolumeException {
Platform.runLater(() -> state.set(State.PROCESSING));
try {
+ if (vaultSettings.usesIndividualMountPath().and(vaultSettings.individualMountPath().isEmpty()).get()) {
+ throw new InvalidSettingsException();
+ }
CryptoFileSystem fs = getCryptoFileSystem(passphrase);
volume = volumeProvider.get();
volume.mount(fs);
diff --git a/main/ui/src/main/resources/fxml/unlock.fxml b/main/ui/src/main/resources/fxml/unlock.fxml
index 43928d9e4..5675556a1 100644
--- a/main/ui/src/main/resources/fxml/unlock.fxml
+++ b/main/ui/src/main/resources/fxml/unlock.fxml
@@ -91,11 +91,7 @@
-
-
-
-
-
+
diff --git a/main/ui/src/main/resources/localization/en.txt b/main/ui/src/main/resources/localization/en.txt
index 42d63b7ce..3018503fe 100644
--- a/main/ui/src/main/resources/localization/en.txt
+++ b/main/ui/src/main/resources/localization/en.txt
@@ -69,8 +69,8 @@ unlock.label.mountName=Drive Name
unlock.label.unlockAfterStartup=Auto-Unlock on Start (Experimental)
unlock.label.revealAfterMount=Reveal Drive
unlock.label.winDriveLetter=Drive Letter
-unlock.label.useOwnMountPath=Use own Mount point
-unlock.label.mountPath=Mount Path
+unlock.label.useOwnMountPath=Use individual mount point
+unlock.label.mountPath=Mount path
unlock.label.mountPathButton=Apply
unlock.label.downloadsPageLink=All Cryptomator versions
unlock.label.advancedHeading=Advanced Options
@@ -82,6 +82,8 @@ unlock.savePassword.delete.confirmation.header=Do you really want to delete the
unlock.savePassword.delete.confirmation.content=The saved password of this vault will be immediately deleted from your system keychain. If you'd like to save your password again, you'd have to unlock your vault with the "Save Password" option enabled.
unlock.choicebox.winDriveLetter.auto=Assign automatically
unlock.errorMessage.wrongPassword=Wrong password
+unlock.errorMessage.wrongPassword=Wrong Password
+unlock.errorMessage.invalidMountPath=Individual mount path is not set.
unlock.errorMessage.unlockFailed=Unlock failed. See log file for details.
unlock.errorMessage.unsupportedVersion.vaultOlderThanSoftware=Unsupported vault. This vault has been created with an older version of Cryptomator.
unlock.errorMessage.unsupportedVersion.softwareOlderThanVault=Unsupported vault. This vault has been created with a newer version of Cryptomator.