Merge branch 'feature/#1289-introduceVaultname' into hotfix/1.5.8

This commit is contained in:
Armin Schrenk
2020-08-28 11:59:56 +02:00
40 changed files with 112 additions and 106 deletions

View File

@@ -8,6 +8,8 @@ package org.cryptomator.common.settings;
import com.google.common.base.Strings;
import com.google.common.io.BaseEncoding;
import javafx.beans.Observable;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.StringBinding;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.ObjectProperty;
@@ -17,7 +19,6 @@ import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import org.apache.commons.lang3.StringUtils;
import org.fxmisc.easybind.EasyBind;
import java.nio.file.Path;
import java.util.Objects;
@@ -34,7 +35,6 @@ public class VaultSettings {
public static final boolean DEFAULT_USES_INDIVIDUAL_MOUNTPATH = false;
public static final boolean DEFAULT_USES_READONLY_MODE = false;
public static final String DEFAULT_MOUNT_FLAGS = "";
public static final String DEFAULT_MOUNT_NAME = "Vault";
public static final int DEFAULT_FILENAME_LENGTH_LIMIT = -1;
public static final WhenUnlocked DEFAULT_ACTION_AFTER_UNLOCK = WhenUnlocked.ASK;
@@ -42,7 +42,7 @@ public class VaultSettings {
private final String id;
private final ObjectProperty<Path> path = new SimpleObjectProperty();
private final StringProperty mountName = new SimpleStringProperty();
private final StringProperty displayName = new SimpleStringProperty();
private final StringProperty winDriveLetter = new SimpleStringProperty();
private final BooleanProperty unlockAfterStartup = new SimpleBooleanProperty(DEFAULT_UNLOCK_AFTER_STARTUP);
private final BooleanProperty revealAfterMount = new SimpleBooleanProperty(DEFAULT_REAVEAL_AFTER_MOUNT);
@@ -53,30 +53,15 @@ public class VaultSettings {
private final IntegerProperty filenameLengthLimit = new SimpleIntegerProperty(DEFAULT_FILENAME_LENGTH_LIMIT);
private final ObjectProperty<WhenUnlocked> actionAfterUnlock = new SimpleObjectProperty<>(DEFAULT_ACTION_AFTER_UNLOCK);
private final StringBinding mountName;
public VaultSettings(String id) {
this.id = Objects.requireNonNull(id);
EasyBind.subscribe(path, this::deriveMountNameFromPathOrUseDefault);
this.mountName = Bindings.createStringBinding(this::normalizeDisplayName, displayName);
}
Observable[] observables() {
return new Observable[]{path, mountName, winDriveLetter, unlockAfterStartup, revealAfterMount, useCustomMountPath, customMountPath, usesReadOnlyMode, mountFlags, filenameLengthLimit, actionAfterUnlock};
}
private void deriveMountNameFromPathOrUseDefault(Path newPath) {
final boolean mountNameSet = !StringUtils.isBlank(mountName.get());
final boolean dirnameExists = (newPath != null) && (newPath.getFileName() != null);
if (!mountNameSet && dirnameExists) {
mountName.set(normalizeMountName(newPath.getFileName().toString()));
} else if (!mountNameSet && !dirnameExists) {
mountName.set(DEFAULT_MOUNT_NAME + id);
} else if (mountNameSet && dirnameExists) {
if (mountName.get().equals(DEFAULT_MOUNT_NAME + id)) {
//this is okay, since this function is only executed if the path changes (aka, the vault is created or added)
mountName.set(newPath.getFileName().toString());
}
}
return new Observable[]{path, displayName, winDriveLetter, unlockAfterStartup, revealAfterMount, useCustomMountPath, customMountPath, usesReadOnlyMode, mountFlags, filenameLengthLimit, actionAfterUnlock};
}
public static VaultSettings withRandomId() {
@@ -89,8 +74,9 @@ public class VaultSettings {
return BaseEncoding.base64Url().encode(randomBytes);
}
public static String normalizeMountName(String mountName) {
String normalizedMountName = StringUtils.stripAccents(mountName);
//visible for testing
String normalizeDisplayName() {
String normalizedMountName = StringUtils.stripAccents(displayName.get());
StringBuilder builder = new StringBuilder();
for (char c : normalizedMountName.toCharArray()) {
if (Character.isWhitespace(c)) {
@@ -118,7 +104,11 @@ public class VaultSettings {
return path;
}
public StringProperty mountName() {
public StringProperty displayName() {
return displayName;
}
public StringBinding mountName() {
return mountName;
}

View File

@@ -21,7 +21,7 @@ class VaultSettingsJsonAdapter {
out.beginObject();
out.name("id").value(value.getId());
out.name("path").value(value.path().get().toString());
out.name("mountName").value(value.mountName().get());
out.name("displayName").value(value.displayName().get());
out.name("winDriveLetter").value(value.winDriveLetter().get());
out.name("unlockAfterStartup").value(value.unlockAfterStartup().get());
out.name("revealAfterMount").value(value.revealAfterMount().get());
@@ -37,7 +37,8 @@ class VaultSettingsJsonAdapter {
public VaultSettings read(JsonReader in) throws IOException {
String id = null;
String path = null;
String mountName = null;
String mountName = null; //see https://github.com/cryptomator/cryptomator/pull/1318
String displayName = null;
String customMountPath = null;
String winDriveLetter = null;
boolean unlockAfterStartup = VaultSettings.DEFAULT_UNLOCK_AFTER_STARTUP;
@@ -54,7 +55,8 @@ class VaultSettingsJsonAdapter {
switch (name) {
case "id" -> id = in.nextString();
case "path" -> path = in.nextString();
case "mountName" -> mountName = in.nextString();
case "mountName" -> mountName = in.nextString(); //see https://github.com/cryptomator/cryptomator/pull/1318
case "displayName" -> displayName = in.nextString();
case "winDriveLetter" -> winDriveLetter = in.nextString();
case "unlockAfterStartup" -> unlockAfterStartup = in.nextBoolean();
case "revealAfterMount" -> revealAfterMount = in.nextBoolean();
@@ -73,7 +75,11 @@ class VaultSettingsJsonAdapter {
in.endObject();
VaultSettings vaultSettings = (id == null) ? VaultSettings.withRandomId() : new VaultSettings(id);
vaultSettings.mountName().set(mountName);
if (displayName != null) { //see https://github.com/cryptomator/cryptomator/pull/1318
vaultSettings.displayName().set(displayName);
} else {
vaultSettings.displayName().set(mountName);
}
vaultSettings.path().set(Paths.get(path));
vaultSettings.winDriveLetter().set(winDriveLetter);
vaultSettings.unlockAfterStartup().set(unlockAfterStartup);

View File

@@ -47,9 +47,9 @@ public class DokanyVolume implements Volume {
@Override
public void mount(CryptoFileSystem fs, String mountFlags) throws VolumeException, IOException {
this.mountPoint = determineMountPoint();
String mountName = vaultSettings.mountName().get();
String mountName = vaultSettings.displayName().get();
try {
this.mount = mountFactory.mount(fs.getPath("/"), mountPoint, mountName, FS_TYPE_NAME, mountFlags.strip());
this.mount = mountFactory.mount(fs.getPath("/"), mountPoint, vaultSettings.mountName().get(), FS_TYPE_NAME, mountFlags.strip());
} catch (MountFailedException e) {
if (vaultSettings.getCustomMountPath().isPresent()) {
LOG.warn("Failed to mount vault into {}. Is this directory currently accessed by another process (e.g. Windows Explorer)?", mountPoint);

View File

@@ -56,7 +56,7 @@ public class Vault {
private final ObjectProperty<VaultState> state;
private final ObjectProperty<Exception> lastKnownException;
private final VaultStats stats;
private final StringBinding displayableName;
private final StringBinding displayName;
private final StringBinding displayablePath;
private final BooleanBinding locked;
private final BooleanBinding processing;
@@ -78,7 +78,7 @@ public class Vault {
this.state = state;
this.lastKnownException = lastKnownException;
this.stats = stats;
this.displayableName = Bindings.createStringBinding(this::getDisplayableName, vaultSettings.path());
this.displayName = Bindings.createStringBinding(this::getDisplayName, vaultSettings.displayName());
this.displayablePath = Bindings.createStringBinding(this::getDisplayablePath, vaultSettings.path());
this.locked = Bindings.createBooleanBinding(this::isLocked, state);
this.processing = Bindings.createBooleanBinding(this::isProcessing, state);
@@ -225,13 +225,12 @@ public class Vault {
return state.get() == VaultState.ERROR;
}
public StringBinding displayableNameProperty() {
return displayableName;
public StringBinding displayNameProperty() {
return displayName;
}
public String getDisplayableName() {
Path p = vaultSettings.path().get();
return p.getFileName().toString();
public String getDisplayName() {
return vaultSettings.displayName().get();
}
public StringBinding accessPointProperty() {

View File

@@ -20,11 +20,11 @@ import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.util.Collection;
import java.util.Optional;
import java.util.ResourceBundle;
import java.util.stream.Collectors;
import static org.cryptomator.common.Constants.MASTERKEY_FILENAME;
@@ -36,10 +36,12 @@ public class VaultListManager {
private final VaultComponent.Builder vaultComponentBuilder;
private final ObservableList<Vault> vaultList;
private final String defaultVaultName;
@Inject
public VaultListManager(VaultComponent.Builder vaultComponentBuilder, Settings settings) {
public VaultListManager(VaultComponent.Builder vaultComponentBuilder, ResourceBundle resourceBundle, Settings settings) {
this.vaultComponentBuilder = vaultComponentBuilder;
this.defaultVaultName = resourceBundle.getString("defaults.vault.vaultName");
this.vaultList = FXCollections.observableArrayList(Vault::observables);
addAll(settings.getDirectories());
@@ -59,14 +61,23 @@ public class VaultListManager {
if (alreadyExistingVault.isPresent()) {
return alreadyExistingVault.get();
} else {
VaultSettings vaultSettings = VaultSettings.withRandomId();
vaultSettings.path().set(normalizedPathToVault);
Vault newVault = create(vaultSettings);
Vault newVault = create(newVaultSettings(normalizedPathToVault));
vaultList.add(newVault);
return newVault;
}
}
private VaultSettings newVaultSettings(Path path) {
VaultSettings vaultSettings = VaultSettings.withRandomId();
vaultSettings.path().set(path);
if (path.getFileName() != null) {
vaultSettings.displayName().set(path.getFileName().toString());
} else {
vaultSettings.displayName().set(defaultVaultName);
}
return vaultSettings;
}
private void addAll(Collection<VaultSettings> vaultSettings) {
Collection<Vault> vaults = vaultSettings.stream().map(this::create).collect(Collectors.toList());
vaultList.addAll(vaults);
@@ -92,7 +103,7 @@ public class VaultListManager {
}
return compBuilder.build().vault();
}
public static VaultState redetermineVaultState(Vault vault) {
VaultState previousState = vault.getState();
return switch (previousState) {

View File

@@ -77,7 +77,7 @@ public class VaultModule {
@DefaultMountFlags
public StringBinding provideDefaultMountFlags(Settings settings, VaultSettings vaultSettings) {
ObjectProperty<VolumeImpl> preferredVolumeImpl = settings.preferredVolumeImpl();
StringProperty mountName = vaultSettings.mountName();
StringProperty mountName = vaultSettings.displayName();
BooleanProperty readOnly = vaultSettings.usesReadOnlyMode();
return Bindings.createStringBinding(() -> {

View File

@@ -98,7 +98,7 @@ public class WebDavVolume implements Volume {
@Override
public Optional<Path> getMountPoint() {
return Optional.ofNullable(mountPoint);
return Optional.ofNullable(mountPoint); //TODO
}
private String getLocalhostAliasOrNull() {

View File

@@ -29,7 +29,7 @@ public class SettingsTest {
Mockito.verify(changeListener, Mockito.times(2)).accept(settings);
// third change (to property of list item):
vaultSettings.mountName().set("asd");
vaultSettings.displayName().set("asd");
Mockito.verify(changeListener, Mockito.times(3)).accept(settings);
}

View File

@@ -23,13 +23,13 @@ public class VaultSettingsJsonAdapterTest {
@Test
public void testDeserialize() throws IOException {
String json = "{\"id\": \"foo\", \"path\": \"/foo/bar\", \"mountName\": \"test\", \"winDriveLetter\": \"X\", \"shouldBeIgnored\": true, \"individualMountPath\": \"/home/test/crypto\", \"mountFlags\":\"--foo --bar\"}";
String json = "{\"id\": \"foo\", \"path\": \"/foo/bar\", \"displayName\": \"test\", \"winDriveLetter\": \"X\", \"shouldBeIgnored\": true, \"individualMountPath\": \"/home/test/crypto\", \"mountFlags\":\"--foo --bar\"}";
JsonReader jsonReader = new JsonReader(new StringReader(json));
VaultSettings vaultSettings = adapter.read(jsonReader);
Assertions.assertEquals("foo", vaultSettings.getId());
Assertions.assertEquals(Paths.get("/foo/bar"), vaultSettings.path().get());
Assertions.assertEquals("test", vaultSettings.mountName().get());
Assertions.assertEquals("test", vaultSettings.displayName().get());
Assertions.assertEquals("X", vaultSettings.winDriveLetter().get());
Assertions.assertEquals("/home/test/crypto", vaultSettings.customMountPath().get());
Assertions.assertEquals("--foo --bar", vaultSettings.mountFlags().get());
@@ -41,7 +41,7 @@ public class VaultSettingsJsonAdapterTest {
public void testSerialize() throws IOException {
VaultSettings vaultSettings = new VaultSettings("test");
vaultSettings.path().set(Paths.get("/foo/bar"));
vaultSettings.mountName().set("mountyMcMountFace");
vaultSettings.displayName().set("mountyMcMountFace");
vaultSettings.mountFlags().set("--foo --bar");
StringWriter buf = new StringWriter();
@@ -55,7 +55,7 @@ public class VaultSettingsJsonAdapterTest {
} else {
MatcherAssert.assertThat(result, CoreMatchers.containsString("\"path\":\"/foo/bar\""));
}
MatcherAssert.assertThat(result, CoreMatchers.containsString("\"mountName\":\"mountyMcMountFace\""));
MatcherAssert.assertThat(result, CoreMatchers.containsString("\"displayName\":\"mountyMcMountFace\""));
MatcherAssert.assertThat(result, CoreMatchers.containsString("\"mountFlags\":\"--foo --bar\""));
}

View File

@@ -8,19 +8,19 @@
*******************************************************************************/
package org.cryptomator.common.settings;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class VaultSettingsTest {
@Test
public void testNormalize() throws Exception {
assertEquals("_", VaultSettings.normalizeMountName(" "));
assertEquals("a", VaultSettings.normalizeMountName("ä"));
assertEquals("C", VaultSettings.normalizeMountName("Ĉ"));
assertEquals("_", VaultSettings.normalizeMountName(":"));
assertEquals("_", VaultSettings.normalizeMountName("汉语"));
@ParameterizedTest
@CsvSource({"a a,a_a", "ä,a", "Ĉ,C", ":,_", "汉语,_"})
public void testNormalize(String test, String expected) {
VaultSettings settings = new VaultSettings("id");
settings.displayName().setValue(test);
assertEquals(expected, settings.normalizeDisplayName());
}
}

View File

@@ -28,7 +28,7 @@ public class VaultModuleTest {
@BeforeEach
public void setup(@TempDir Path tmpDir) {
Mockito.when(vaultSettings.mountName()).thenReturn(new SimpleStringProperty("TEST"));
Mockito.when(vaultSettings.displayName()).thenReturn(new SimpleStringProperty("TEST"));
Mockito.when(vaultSettings.usesReadOnlyMode()).thenReturn(new SimpleBooleanProperty(true));
System.setProperty("user.home", tmpDir.toString());
}

View File

@@ -28,7 +28,7 @@
<cryptomator.jni.version>2.2.3</cryptomator.jni.version>
<cryptomator.fuse.version>1.2.3</cryptomator.fuse.version>
<cryptomator.dokany.version>1.1.15</cryptomator.dokany.version>
<cryptomator.webdav.version>1.0.11</cryptomator.webdav.version>
<cryptomator.webdav.version>1.0.12</cryptomator.webdav.version>
<!-- 3rd party dependencies -->
<javafx.version>14</javafx.version>

View File

@@ -68,7 +68,7 @@ public class ChangePasswordController implements FxController {
public void finish() {
try {
CryptoFileSystemProvider.changePassphrase(vault.getPath(), MASTERKEY_FILENAME, oldPasswordField.getCharacters(), newPassword.get());
LOG.info("Successfully changed password for {}", vault.getDisplayableName());
LOG.info("Successfully changed password for {}", vault.getDisplayName());
window.close();
updatePasswordInSystemkeychain();
} catch (IOException e) {
@@ -85,7 +85,7 @@ public class ChangePasswordController implements FxController {
if (keychain.isPresent()) {
try {
keychain.get().changePassphrase(vault.getId(), CharBuffer.wrap(newPassword.get()));
LOG.info("Successfully updated password in system keychain for {}", vault.getDisplayableName());
LOG.info("Successfully updated password in system keychain for {}", vault.getDisplayName());
} catch (KeychainAccessException e) {
LOG.error("Failed to update password in system keychain.", e);
}

View File

@@ -44,8 +44,8 @@ public class VaultService {
*/
public Task<Vault> createRevealTask(Vault vault) {
Task<Vault> task = new RevealVaultTask(vault);
task.setOnSucceeded(evt -> LOG.info("Revealed {}", vault.getDisplayableName()));
task.setOnFailed(evt -> LOG.error("Failed to reveal " + vault.getDisplayableName(), evt.getSource().getException()));
task.setOnSucceeded(evt -> LOG.info("Revealed {}", vault.getDisplayName()));
task.setOnFailed(evt -> LOG.error("Failed to reveal " + vault.getDisplayName(), evt.getSource().getException()));
return task;
}
@@ -68,8 +68,8 @@ public class VaultService {
*/
public Task<Vault> createLockTask(Vault vault, boolean forced) {
Task<Vault> task = new LockVaultTask(vault, forced);
task.setOnSucceeded(evt -> LOG.info("Locked {}", vault.getDisplayableName()));
task.setOnFailed(evt -> LOG.error("Failed to lock " + vault.getDisplayableName(), evt.getSource().getException()));
task.setOnSucceeded(evt -> LOG.info("Locked {}", vault.getDisplayName()));
task.setOnFailed(evt -> LOG.error("Failed to lock " + vault.getDisplayName(), evt.getSource().getException()));
return task;
}
@@ -94,7 +94,7 @@ public class VaultService {
List<Task<Vault>> lockTasks = vaults.stream().map(v -> new LockVaultTask(v, forced)).collect(Collectors.toUnmodifiableList());
lockTasks.forEach(executorService::execute);
Task<Collection<Vault>> task = new WaitForTasksTask(lockTasks);
String vaultNames = vaults.stream().map(Vault::getDisplayableName).collect(Collectors.joining(", "));
String vaultNames = vaults.stream().map(Vault::getDisplayName).collect(Collectors.joining(", "));
task.setOnSucceeded(evt -> LOG.info("Locked {}", vaultNames));
task.setOnFailed(evt -> LOG.error("Failed to lock vaults " + vaultNames, evt.getSource().getException()));
return task;

View File

@@ -41,7 +41,7 @@ public class ForgetPasswordController implements FxController {
if (keychain.isPresent()) {
try {
keychain.get().deletePassphrase(vault.getId());
LOG.debug("Forgot password for vault {}.", vault.getDisplayableName());
LOG.debug("Forgot password for vault {}.", vault.getDisplayName());
confirmedResult.setValue(true);
} catch (KeychainAccessException e) {
LOG.error("Failed to remove entry from system keychain.", e);

View File

@@ -100,7 +100,7 @@ public class FxApplication extends Application {
public void startUnlockWorkflow(Vault vault, Optional<Stage> owner) {
Platform.runLater(() -> {
unlockWindowBuilderProvider.get().vault(vault).owner(owner).build().startUnlockWorkflow();
LOG.debug("Showing UnlockWindow for {}", vault.getDisplayableName());
LOG.debug("Showing UnlockWindow for {}", vault.getDisplayName());
});
}

View File

@@ -116,10 +116,10 @@ public class MigrationRunController implements FxController {
return migrators.needsMigration(vault.getPath(), MASTERKEY_FILENAME);
}).onSuccess(needsAnotherMigration -> {
if (needsAnotherMigration) {
LOG.info("Migration of '{}' succeeded, but another migration is required.", vault.getDisplayableName());
LOG.info("Migration of '{}' succeeded, but another migration is required.", vault.getDisplayName());
vault.setState(VaultState.NEEDS_MIGRATION);
} else {
LOG.info("Migration of '{}' succeeded.", vault.getDisplayableName());
LOG.info("Migration of '{}' succeeded.", vault.getDisplayName());
vault.setState(VaultState.LOCKED);
passwordField.wipe();
window.setScene(successScene.get());

View File

@@ -53,7 +53,7 @@ public class QuitController implements FxController {
Task<Collection<Vault>> lockAllTask = vaultService.createLockAllTask(unlockedVaults, false);
lockAllTask.setOnSucceeded(evt -> {
LOG.info("Locked {}", lockAllTask.getValue().stream().map(Vault::getDisplayableName).collect(Collectors.joining(", ")));
LOG.info("Locked {}", lockAllTask.getValue().stream().map(Vault::getDisplayName).collect(Collectors.joining(", ")));
if (unlockedVaults.isEmpty()) {
window.close();
response.performQuit();

View File

@@ -9,7 +9,6 @@ import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.stage.Modality;
import javafx.stage.Stage;
import org.cryptomator.common.vaults.Vault;
@@ -25,7 +24,6 @@ import org.cryptomator.ui.common.StageFactory;
import javax.inject.Named;
import javax.inject.Provider;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
@@ -107,7 +105,7 @@ abstract class RecoveryKeyModule {
@IntoMap
@FxControllerKey(RecoveryKeyDisplayController.class)
static FxController provideRecoveryKeyDisplayController(@RecoveryKeyWindow Stage window, @RecoveryKeyWindow Vault vault, @RecoveryKeyWindow StringProperty recoveryKey, ResourceBundle localization) {
return new RecoveryKeyDisplayController(window, vault.getDisplayableName(), recoveryKey.get(), localization);
return new RecoveryKeyDisplayController(window, vault.getDisplayName(), recoveryKey.get(), localization);
}
@Binds

View File

@@ -34,7 +34,7 @@ public class RemoveVaultController implements FxController {
@FXML
public void finish() {
vaults.remove(vault);
LOG.debug("Removing vault {}.", vault.getDisplayableName());
LOG.debug("Removing vault {}.", vault.getDisplayName());
window.close();
}
}

View File

@@ -80,7 +80,7 @@ class TrayMenuController {
}
private Menu buildSubmenu(Vault vault) {
Menu submenu = new Menu(vault.getDisplayableName());
Menu submenu = new Menu(vault.getDisplayName());
if (vault.isLocked()) {
MenuItem unlockItem = new MenuItem(resourceBundle.getString("traymenu.vault.unlock"));

View File

@@ -77,7 +77,7 @@ public class UnlockController implements FxController {
this.unlockButtonContentDisplay = Bindings.createObjectBinding(this::getUnlockButtonContentDisplay, passwordEntryLock.awaitingInteraction());
this.userInteractionDisabled = passwordEntryLock.awaitingInteraction().not();
this.unlockButtonDisabled = new SimpleBooleanProperty();
this.vaultName = WeakBindings.bindString(vault.displayableNameProperty());
this.vaultName = WeakBindings.bindString(vault.displayNameProperty());
this.window.setOnCloseRequest(windowEvent -> cancel());
}

View File

@@ -82,7 +82,7 @@ abstract class UnlockModule {
@UnlockScoped
static Stage provideStage(StageFactory factory, @UnlockWindow Vault vault, @Named("unlockWindowOwner") Optional<Stage> owner) {
Stage stage = factory.create();
stage.setTitle(vault.getDisplayableName());
stage.setTitle(vault.getDisplayName());
stage.setResizable(false);
if (owner.isPresent()) {
stage.initOwner(owner.get());

View File

@@ -128,7 +128,7 @@ public class UnlockWorkflow extends Task<Boolean> {
}
private void handleSuccess() {
LOG.info("Unlock of '{}' succeeded.", vault.getDisplayableName());
LOG.info("Unlock of '{}' succeeded.", vault.getDisplayName());
if (savePassword.get()) {
savePasswordToSystemkeychain();
}

View File

@@ -3,6 +3,7 @@ package org.cryptomator.ui.vaultoptions;
import javafx.fxml.FXML;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ChoiceBox;
import javafx.scene.control.TextField;
import javafx.util.StringConverter;
import org.cryptomator.common.settings.UiTheme;
import org.cryptomator.common.settings.WhenUnlocked;
@@ -18,6 +19,7 @@ public class GeneralVaultOptionsController implements FxController {
private final Vault vault;
private final ResourceBundle resourceBundle;
public TextField vaultName;
public CheckBox unlockOnStartupCheckbox;
public ChoiceBox<WhenUnlocked> actionAfterUnlockChoiceBox;
@@ -29,6 +31,7 @@ public class GeneralVaultOptionsController implements FxController {
@FXML
public void initialize() {
vaultName.textProperty().bindBidirectional(vault.getVaultSettings().displayName());
unlockOnStartupCheckbox.selectedProperty().bindBidirectional(vault.getVaultSettings().unlockAfterStartup());
actionAfterUnlockChoiceBox.getItems().addAll(WhenUnlocked.values());
actionAfterUnlockChoiceBox.valueProperty().bindBidirectional(vault.getVaultSettings().actionAfterUnlock());

View File

@@ -42,7 +42,6 @@ public class MountOptionsController implements FxController {
private final BooleanBinding webDavAndWindows;
private final WindowsDriveLetters windowsDriveLetters;
private final ResourceBundle resourceBundle;
public TextField driveName;
public CheckBox readOnlyCheckbox;
public CheckBox customMountFlagsCheckbox;
public TextField mountFlags;
@@ -63,7 +62,6 @@ public class MountOptionsController implements FxController {
@FXML
public void initialize() {
driveName.textProperty().bindBidirectional(vault.getVaultSettings().mountName());
// readonly:
readOnlyCheckbox.selectedProperty().bindBidirectional(vault.getVaultSettings().usesReadOnlyMode());

View File

@@ -5,7 +5,6 @@ import dagger.Module;
import dagger.Provides;
import dagger.multibindings.IntoMap;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.stage.Modality;
import javafx.stage.Stage;
import org.cryptomator.common.vaults.Vault;
@@ -20,9 +19,7 @@ import org.cryptomator.ui.common.StageFactory;
import org.cryptomator.ui.mainwindow.MainWindow;
import org.cryptomator.ui.recoverykey.RecoveryKeyComponent;
import javax.inject.Named;
import javax.inject.Provider;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
@@ -41,7 +38,7 @@ abstract class VaultOptionsModule {
@VaultOptionsScoped
static Stage provideStage(StageFactory factory, @MainWindow Stage owner, @VaultOptionsWindow Vault vault) {
Stage stage = factory.create();
stage.setTitle(vault.getDisplayableName());
stage.setTitle(vault.getDisplayName());
stage.setResizable(true);
stage.setMinWidth(400);
stage.setMinHeight(300);

View File

@@ -30,7 +30,7 @@
<Region VBox.vgrow="ALWAYS"/>
<FormattedLabel format="%addvaultwizard.success.nextStepsInstructions" arg1="${controller.vault.displayableName}" wrapText="true" HBox.hgrow="ALWAYS"/>
<FormattedLabel format="%addvaultwizard.success.nextStepsInstructions" arg1="${controller.vault.displayName}" wrapText="true" HBox.hgrow="ALWAYS"/>
<Region VBox.vgrow="ALWAYS"/>

View File

@@ -19,7 +19,7 @@
</padding>
<children>
<VBox spacing="6">
<FormattedLabel format="%changepassword.enterOldPassword" arg1="${controller.vault.displayableName}" wrapText="true"/>
<FormattedLabel format="%changepassword.enterOldPassword" arg1="${controller.vault.displayName}" wrapText="true"/>
<NiceSecurePasswordField fx:id="oldPasswordField"/>
</VBox>

View File

@@ -21,7 +21,7 @@
</padding>
<children>
<VBox spacing="6" visible="${!controller.vault.processing}" managed="${!controller.vault.processing}">
<FormattedLabel format="%migration.run.enterPassword" arg1="${controller.vault.displayableName}" wrapText="true"/>
<FormattedLabel format="%migration.run.enterPassword" arg1="${controller.vault.displayName}" wrapText="true"/>
<NiceSecurePasswordField fx:id="passwordField"/>
</VBox>

View File

@@ -28,7 +28,7 @@
</StackPane>
<VBox spacing="6" HBox.hgrow="ALWAYS">
<FormattedLabel format="%migration.start.prompt" arg1="${controller.vault.displayableName}" wrapText="true" />
<FormattedLabel format="%migration.start.prompt" arg1="${controller.vault.displayName}" wrapText="true" />
<CheckBox fx:id="confirmSyncDone" text="%migration.start.confirm"/>
</VBox>
</HBox>

View File

@@ -25,7 +25,7 @@
<Circle styleClass="glyph-icon-primary" radius="24"/>
<FontAwesome5IconView styleClass="glyph-icon-white" glyph="CHECK" glyphSize="24"/>
</StackPane>
<FormattedLabel format="%migration.success.nextStepsInstructions" arg1="${controller.vault.displayableName}" wrapText="true" HBox.hgrow="ALWAYS"/>
<FormattedLabel format="%migration.success.nextStepsInstructions" arg1="${controller.vault.displayName}" wrapText="true" HBox.hgrow="ALWAYS"/>
</HBox>
<VBox alignment="BOTTOM_CENTER" VBox.vgrow="ALWAYS">

View File

@@ -20,7 +20,7 @@
</padding>
<children>
<VBox spacing="6">
<FormattedLabel format="%recoveryKey.enterPassword.prompt" arg1="${controller.vault.displayableName}" wrapText="true"/>
<FormattedLabel format="%recoveryKey.enterPassword.prompt" arg1="${controller.vault.displayName}" wrapText="true"/>
<NiceSecurePasswordField fx:id="passwordField" HBox.hgrow="ALWAYS"/>
</VBox>

View File

@@ -21,7 +21,7 @@
<Insets topRightBottomLeft="12"/>
</padding>
<children>
<FormattedLabel format="%recoveryKey.recover.prompt" arg1="${controller.vault.displayableName}" wrapText="true"/>
<FormattedLabel format="%recoveryKey.recover.prompt" arg1="${controller.vault.displayName}" wrapText="true"/>
<TextArea wrapText="true" prefRowCount="4" fx:id="textarea" textFormatter="${controller.recoveryKeyTextFormatter}" onKeyPressed="#onKeyPressed"/>

View File

@@ -28,7 +28,7 @@
<FontAwesome5IconView styleClass="glyph-icon-white" glyph="CHECK" glyphSize="24"/>
</StackPane>
<VBox spacing="6">
<FormattedLabel format="%unlock.success.message" arg1="${controller.vault.displayableName}" wrapText="true" HBox.hgrow="ALWAYS"/>
<FormattedLabel format="%unlock.success.message" arg1="${controller.vault.displayName}" wrapText="true" HBox.hgrow="ALWAYS"/>
<CheckBox text="%unlock.success.rememberChoice" fx:id="rememberChoiceCheckbox"/>
</VBox>
</HBox>

View File

@@ -26,9 +26,9 @@
</StackPane>
<VBox spacing="4" HBox.hgrow="ALWAYS">
<HBox spacing="12">
<Label styleClass="label-large" text="${controller.vault.displayableName}">
<Label styleClass="label-large" text="${controller.vault.displayName}">
<tooltip>
<Tooltip text="${controller.vault.displayableName}"/>
<Tooltip text="${controller.vault.displayName}"/>
</tooltip>
</Label>
<Region HBox.hgrow="ALWAYS"/>

View File

@@ -20,7 +20,7 @@
<FontAwesome5IconView glyph="${controller.glyph}" HBox.hgrow="NEVER" glyphSize="16"/>
</VBox>
<VBox spacing="4" HBox.hgrow="ALWAYS">
<Label styleClass="header-label" text="${controller.vault.displayableName}"/>
<Label styleClass="header-label" text="${controller.vault.displayName}"/>
<Label styleClass="detail-label" text="${controller.vault.displayablePath}" textOverrun="CENTER_ELLIPSIS"/>
</VBox>
</children>

View File

@@ -2,10 +2,11 @@
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.CheckBox?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.control.ChoiceBox?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<VBox xmlns="http://javafx.com/javafx"
xmlns:fx="http://javafx.com/fxml"
fx:controller="org.cryptomator.ui.vaultoptions.GeneralVaultOptionsController"
@@ -14,6 +15,11 @@
<Insets topRightBottomLeft="12"/>
</padding>
<children>
<HBox spacing="6" alignment="CENTER_LEFT">
<Label text="%vaultOptions.general.vaultName"/>
<TextField fx:id="vaultName"/>
</HBox>
<CheckBox text="%vaultOptions.general.unlockAfterStartup" fx:id="unlockOnStartupCheckbox"/>
<HBox spacing="6" alignment="CENTER_LEFT">

View File

@@ -23,11 +23,6 @@
<Insets topRightBottomLeft="12"/>
</padding>
<children>
<HBox spacing="6" alignment="CENTER_LEFT">
<Label text="%vaultOptions.mount.driveName"/>
<AlphanumericTextField fx:id="driveName"/>
</HBox>
<CheckBox fx:id="readOnlyCheckbox" text="%vaultOptions.mount.readonly"/>
<CheckBox fx:id="customMountFlagsCheckbox" text="%vaultOptions.mount.customMountFlags" onAction="#toggleUseCustomMountFlags" visible="${!controller.webDavAndWindows}" managed="${!controller.webDavAndWindows}"/>

View File

@@ -17,6 +17,9 @@ generic.button.print=Print
generic.error.title=An unexpected error occured
generic.error.instruction=This should not have happened. Please report the error text below and include a description of what steps did lead to this error.
# Defaults
defaults.vault.vaultName=Vault
# Tray Menu
traymenu.showMainWindow=Show
traymenu.showPreferencesWindow=Preferences
@@ -214,6 +217,7 @@ wrongFileAlert.link=For further assistance, visit
# Vault Options
## General
vaultOptions.general=General
vaultOptions.general.vaultName=Vault Name
vaultOptions.general.unlockAfterStartup=Unlock vault when starting Cryptomator
vaultOptions.general.actionAfterUnlock=After successful unlock
vaultOptions.general.actionAfterUnlock.ignore=Do nothing
@@ -222,7 +226,6 @@ vaultOptions.general.actionAfterUnlock.ask=Ask
## Mount
vaultOptions.mount=Mounting
vaultOptions.mount.readonly=Read-Only
vaultOptions.mount.driveName=Drive Name
vaultOptions.mount.customMountFlags=Custom Mount Flags
vaultOptions.mount.winDriveLetterOccupied=occupied
vaultOptions.mount.mountPoint=Mount Point