diff --git a/main/commons/src/test/java/org/cryptomator/common/settings/VaultSettingsJsonAdapterTest.java b/main/commons/src/test/java/org/cryptomator/common/settings/VaultSettingsJsonAdapterTest.java index 62a37a5c2..f7698d2ba 100644 --- a/main/commons/src/test/java/org/cryptomator/common/settings/VaultSettingsJsonAdapterTest.java +++ b/main/commons/src/test/java/org/cryptomator/common/settings/VaultSettingsJsonAdapterTest.java @@ -51,7 +51,11 @@ public class VaultSettingsJsonAdapterTest { String result = buf.toString(); MatcherAssert.assertThat(result, CoreMatchers.containsString("\"id\":\"test\"")); - MatcherAssert.assertThat(result, CoreMatchers.containsString("\"path\":\"/foo/bar\"")); + if(System.getProperty("os.name").contains("Windows")){ + MatcherAssert.assertThat(result, CoreMatchers.containsString("\"path\":\"\\\\foo\\\\bar\"")); + } else { + MatcherAssert.assertThat(result, CoreMatchers.containsString("\"path\":\"/foo/bar\"")); + } MatcherAssert.assertThat(result, CoreMatchers.containsString("\"mountName\":\"mountyMcMountFace\"")); MatcherAssert.assertThat(result, CoreMatchers.containsString("\"mountFlags\":\"--foo --bar\"")); } 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 ac2d1fb37..59400d84b 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 @@ -33,7 +33,6 @@ 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; import org.cryptomator.common.settings.Settings; import org.cryptomator.common.settings.VaultSettings; @@ -78,7 +77,7 @@ public class UnlockController implements ViewController { private final Stage mainWindow; private final Localization localization; private final WindowsDriveLetters driveLetters; - private final ChangeListener driveLetterChangeListener = this::winDriveLetterDidChange; + private final ChangeListener driveLetterChangeListener = this::winDriveLetterDidChange; private final Optional keychainAccess; private final Settings settings; private final ExecutorService executor; @@ -129,7 +128,7 @@ public class UnlockController implements ViewController { private CheckBox useCustomWinDriveLetter; @FXML - private ChoiceBox winDriveLetter; + private ChoiceBox winDriveLetter; @FXML private CheckBox useCustomMountPoint; @@ -256,6 +255,7 @@ public class UnlockController implements ViewController { winDriveLetter.visibleProperty().bind(useCustomMountPoint.selectedProperty().not()); winDriveLetter.managedProperty().bind(useCustomMountPoint.selectedProperty().not()); + useCustomWinDriveLetter.setSelected(!vaultSettings.usesIndividualMountPath().get()); useCustomWinDriveLetter.visibleProperty().bind(useCustomMountPoint.selectedProperty().not()); useCustomWinDriveLetter.managedProperty().bind(useCustomMountPoint.selectedProperty().not()); } @@ -309,7 +309,7 @@ public class UnlockController implements ViewController { } } - private void mountNameDidChange(@SuppressWarnings("unused") ObservableValue property, @SuppressWarnings("unused")String oldValue, String newValue) { + private void mountNameDidChange(@SuppressWarnings("unused") ObservableValue property, @SuppressWarnings("unused") String oldValue, String newValue) { // newValue is guaranteed to be a-z0-9_, see #filterAlphanumericKeyEvents if (newValue.isEmpty()) { mountName.setText(vault.getMountName()); @@ -321,7 +321,7 @@ public class UnlockController implements ViewController { } } - private void useReadOnlyDidChange(@SuppressWarnings("unused") ObservableValue property, @SuppressWarnings("unused")Boolean oldValue, Boolean newValue) { + private void useReadOnlyDidChange(@SuppressWarnings("unused") ObservableValue property, @SuppressWarnings("unused") Boolean oldValue, Boolean newValue) { vault.getVaultSettings().usesReadOnlyMode().setValue(newValue); if (!useCustomMountFlags.isSelected()) { mountFlags.setText(vault.getMountFlags()); // update default flags @@ -329,14 +329,14 @@ public class UnlockController implements ViewController { } - private void useCustomMountFlagsDidChange(@SuppressWarnings("unused") ObservableValue property, @SuppressWarnings("unused")Boolean oldValue, Boolean newValue) { + private void useCustomMountFlagsDidChange(@SuppressWarnings("unused") ObservableValue property, @SuppressWarnings("unused") Boolean oldValue, Boolean newValue) { if (!newValue) { vault.setMountFlags(VaultSettings.DEFAULT_MOUNT_FLAGS); mountFlags.setText(vault.getMountFlags()); } } - private void mountFlagsDidChange(@SuppressWarnings("unused") ObservableValue property, @SuppressWarnings("unused")String oldValue, String newValue) { + private void mountFlagsDidChange(@SuppressWarnings("unused") ObservableValue property, @SuppressWarnings("unused") String oldValue, String newValue) { if (useCustomMountFlags.isSelected()) { vault.setMountFlags(newValue); } @@ -359,26 +359,33 @@ public class UnlockController implements ViewController { } } + @FXML + public void didClickCustomMountPointCheckbox() { + useCustomWinDriveLetter.setSelected(vault.getWinDriveLetter() != null); + } + /** * Converts 'C' to "C:" to translate between model and GUI. */ - private class WinDriveLetterLabelConverter extends StringConverter { + private class WinDriveLetterLabelConverter extends StringConverter { @Override - public String toString(Character letter) { - if (letter == null) { + public String toString(Path root) { + if (root == null) { return localization.getString("unlock.choicebox.winDriveLetter.auto"); + } else if (root.endsWith("occupied")) { + return root.getRoot().toString().substring(0, 1) + " (" + localization.getString("unlock.choicebox.winDriveLetter.occupied") + ")"; } else { - return letter + ":"; + return root.toString().substring(0, 1); } } @Override - public Character fromString(String string) { + public Path fromString(String string) { if (localization.getString("unlock.choicebox.winDriveLetter.auto").equals(string)) { return null; } else { - return CharUtils.toCharacterObject(string); + return Path.of(string); } } @@ -387,37 +394,41 @@ public class UnlockController implements ViewController { /** * Natural sorting of ASCII letters, but null always on first, as this is "auto-assign". */ - private static class WinDriveLetterComparator implements Comparator { + private static class WinDriveLetterComparator implements Comparator { @Override - public int compare(Character c1, Character c2) { + public int compare(Path c1, Path c2) { if (c1 == null) { return -1; } else if (c2 == null) { return 1; } else { - return c1 - c2; + return c1.compareTo(c2); } } } - private void winDriveLetterDidChange(@SuppressWarnings("unused") ObservableValue property, @SuppressWarnings("unused") Character oldValue, Character newValue) { + private void winDriveLetterDidChange(@SuppressWarnings("unused") ObservableValue property, @SuppressWarnings("unused") Path oldValue, Path newValue) { vault.setWinDriveLetter(newValue); } private void chooseSelectedDriveLetter() { assert SystemUtils.IS_OS_WINDOWS; // if the vault prefers a drive letter, that is currently occupied, this is our last chance to reset this: - if (vault.getWinDriveLetter() != null && driveLetters.getOccupiedDriveLetters().contains(vault.getWinDriveLetter())) { - vault.setWinDriveLetter(null); - } - final Character letter = vault.getWinDriveLetter(); - if (letter == null) { + if (vault.getWinDriveLetter() != null) { + final Path pickedRoot = Path.of(vault.getWinDriveLetter() + ":\\"); + if (driveLetters.getOccupiedDriveLetters().contains(pickedRoot)) { + Path alteredPath = pickedRoot.resolve("occupied"); + this.winDriveLetter.getItems().add(alteredPath); + this.winDriveLetter.getSelectionModel().select(alteredPath); + } else { + this.winDriveLetter.getSelectionModel().select(pickedRoot); + } + } else { // first option is known to be 'auto-assign' due to #WinDriveLetterComparator. this.winDriveLetter.getSelectionModel().selectFirst(); - } else { - this.winDriveLetter.getSelectionModel().select(letter); } + } // **************************************** 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 325f6ba97..42f5d0748 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 @@ -288,10 +288,11 @@ public class Vault { } } - public void setWinDriveLetter(Character winDriveLetter) { - if (winDriveLetter == null) { + public void setWinDriveLetter(Path root) { + if (root == null) { vaultSettings.winDriveLetter().set(null); } else { + char winDriveLetter = root.toString().charAt(0); vaultSettings.winDriveLetter().set(String.valueOf(winDriveLetter)); } } diff --git a/main/ui/src/main/java/org/cryptomator/ui/model/WindowsDriveLetters.java b/main/ui/src/main/java/org/cryptomator/ui/model/WindowsDriveLetters.java index c42696c01..6b8bdef9b 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/model/WindowsDriveLetters.java +++ b/main/ui/src/main/java/org/cryptomator/ui/model/WindowsDriveLetters.java @@ -5,7 +5,6 @@ *******************************************************************************/ package org.cryptomator.ui.model; -import org.apache.commons.lang3.CharUtils; import org.apache.commons.lang3.SystemUtils; import org.cryptomator.common.FxApplicationScoped; import org.slf4j.Logger; @@ -24,11 +23,11 @@ import java.util.stream.StreamSupport; public final class WindowsDriveLetters { private static final Logger LOG = LoggerFactory.getLogger(WindowsDriveLetters.class); - private static final Set D_TO_Z; + private static final Set D_TO_Z; static { try (IntStream stream = IntStream.rangeClosed('D', 'Z')) { - D_TO_Z = stream.mapToObj(i -> (char) i).collect(Collectors.toSet()); + D_TO_Z = stream.mapToObj(i -> Path.of(((char) i)+":\\")).collect(Collectors.toSet()); } } @@ -36,19 +35,19 @@ public final class WindowsDriveLetters { public WindowsDriveLetters() { } - public Set getOccupiedDriveLetters() { + public Set getOccupiedDriveLetters() { if (!SystemUtils.IS_OS_WINDOWS) { LOG.warn("Attempted to get occupied drive letters on non-Windows machine."); return Set.of(); } else { Iterable rootDirs = FileSystems.getDefault().getRootDirectories(); - return StreamSupport.stream(rootDirs.spliterator(), false).map(Path::toString).map(CharUtils::toChar).map(Character::toUpperCase).collect(Collectors.toSet()); + return StreamSupport.stream(rootDirs.spliterator(), false).collect(Collectors.toSet()); } } - public Set getAvailableDriveLetters() { - Set occupiedDriveLetters = getOccupiedDriveLetters(); - Predicate isOccupiedDriveLetter = occupiedDriveLetters::contains; + public Set getAvailableDriveLetters() { + Set occupiedDriveLetters = getOccupiedDriveLetters(); + Predicate isOccupiedDriveLetter = occupiedDriveLetters::contains; return D_TO_Z.stream().filter(isOccupiedDriveLetter.negate()).collect(Collectors.toSet()); } diff --git a/main/ui/src/main/resources/fxml/unlock.fxml b/main/ui/src/main/resources/fxml/unlock.fxml index 0dfc523e9..28108966f 100644 --- a/main/ui/src/main/resources/fxml/unlock.fxml +++ b/main/ui/src/main/resources/fxml/unlock.fxml @@ -76,26 +76,28 @@ - - + + +