Easy to use - work on encrypted files as if they were not
+ https://static.cryptomator.org/desktop/flathubScreenshots/MainWindowUnlocked_light.png
diff --git a/src/main/java/org/cryptomator/common/settings/VaultSettings.java b/src/main/java/org/cryptomator/common/settings/VaultSettings.java
index fd21fc197..5112415b4 100644
--- a/src/main/java/org/cryptomator/common/settings/VaultSettings.java
+++ b/src/main/java/org/cryptomator/common/settings/VaultSettings.java
@@ -58,6 +58,7 @@ public class VaultSettings {
public final StringExpression mountName;
public final StringProperty mountService;
public final IntegerProperty port;
+ public final StringProperty lastKnownKeyLoader;
VaultSettings(VaultSettingsJson json) {
this.id = json.id;
@@ -74,6 +75,7 @@ public class VaultSettings {
this.mountPoint = new SimpleObjectProperty<>(this, "mountPoint", json.mountPoint == null ? null : Path.of(json.mountPoint));
this.mountService = new SimpleStringProperty(this, "mountService", json.mountService);
this.port = new SimpleIntegerProperty(this, "port", json.port);
+ this.lastKnownKeyLoader = new SimpleStringProperty(this, "lastKnownKeyLoader", json.lastKnownKeyLoader);
// mount name is no longer an explicit setting, see https://github.com/cryptomator/cryptomator/pull/1318
this.mountName = StringExpression.stringExpression(Bindings.createStringBinding(() -> {
final String name;
@@ -99,7 +101,7 @@ public class VaultSettings {
}
Observable[] observables() {
- return new Observable[]{actionAfterUnlock, autoLockIdleSeconds, autoLockWhenIdle, displayName, maxCleartextFilenameLength, mountFlags, mountPoint, path, revealAfterMount, unlockAfterStartup, usesReadOnlyMode, port, mountService};
+ return new Observable[]{actionAfterUnlock, autoLockIdleSeconds, autoLockWhenIdle, displayName, maxCleartextFilenameLength, mountFlags, mountPoint, path, revealAfterMount, unlockAfterStartup, usesReadOnlyMode, port, mountService, lastKnownKeyLoader};
}
public static VaultSettings withRandomId() {
@@ -130,6 +132,7 @@ public class VaultSettings {
json.mountPoint = mountPoint.map(Path::toString).getValue();
json.mountService = mountService.get();
json.port = port.get();
+ json.lastKnownKeyLoader = lastKnownKeyLoader.get();
return json;
}
diff --git a/src/main/java/org/cryptomator/common/settings/VaultSettingsJson.java b/src/main/java/org/cryptomator/common/settings/VaultSettingsJson.java
index 43aa204e8..870b74e07 100644
--- a/src/main/java/org/cryptomator/common/settings/VaultSettingsJson.java
+++ b/src/main/java/org/cryptomator/common/settings/VaultSettingsJson.java
@@ -48,6 +48,9 @@ class VaultSettingsJson {
@JsonProperty("mountService")
String mountService;
+ @JsonProperty("lastKnownKeyLoader")
+ String lastKnownKeyLoader;
+
@JsonProperty("port")
int port = VaultSettings.DEFAULT_PORT;
diff --git a/src/main/java/org/cryptomator/common/vaults/VaultListManager.java b/src/main/java/org/cryptomator/common/vaults/VaultListManager.java
index 87faff77a..c362ca0c0 100644
--- a/src/main/java/org/cryptomator/common/vaults/VaultListManager.java
+++ b/src/main/java/org/cryptomator/common/vaults/VaultListManager.java
@@ -27,6 +27,7 @@ import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.util.Collection;
import java.util.List;
+import java.util.Objects;
import java.util.Optional;
import java.util.ResourceBundle;
@@ -49,9 +50,9 @@ public class VaultListManager {
@Inject
public VaultListManager(ObservableList vaultList, //
AutoLocker autoLocker, //
- List mountServices,
- VaultComponent.Factory vaultComponentFactory,
- ResourceBundle resourceBundle,
+ List mountServices, //
+ VaultComponent.Factory vaultComponentFactory, //
+ ResourceBundle resourceBundle, //
Settings settings) {
this.vaultList = vaultList;
this.autoLocker = autoLocker;
@@ -114,6 +115,10 @@ public class VaultListManager {
private Vault create(VaultSettings vaultSettings) {
var wrapper = new VaultConfigCache(vaultSettings);
try {
+ if (Objects.isNull(vaultSettings.lastKnownKeyLoader.get())) {
+ var keyIdScheme = wrapper.get().getKeyId().getScheme();
+ vaultSettings.lastKnownKeyLoader.set(keyIdScheme);
+ }
var vaultState = determineVaultState(vaultSettings.path.get());
if (vaultState == LOCKED) { //for legacy reasons: pre v8 vault do not have a config, but they are in the NEEDS_MIGRATION state
wrapper.reloadConfig();
diff --git a/src/main/java/org/cryptomator/ui/addvaultwizard/ReadmeGenerator.java b/src/main/java/org/cryptomator/ui/addvaultwizard/ReadmeGenerator.java
index 2ffda4d73..a25384c78 100644
--- a/src/main/java/org/cryptomator/ui/addvaultwizard/ReadmeGenerator.java
+++ b/src/main/java/org/cryptomator/ui/addvaultwizard/ReadmeGenerator.java
@@ -76,8 +76,10 @@ public class ReadmeGenerator {
input.chars().forEachOrdered(c -> {
if (c < 128) {
sb.append((char) c);
+ } else if (c <= 0xFF) {
+ sb.append("\\'").append(String.format("%02X", c));
} else if (c < 0xFFFF) {
- sb.append("\\u").append(c);
+ sb.append("\\uc1\\u").append(c);
}
});
}
diff --git a/src/main/java/org/cryptomator/ui/convertvault/HubToPasswordConvertController.java b/src/main/java/org/cryptomator/ui/convertvault/HubToPasswordConvertController.java
index fd6d49b89..dc95f7051 100644
--- a/src/main/java/org/cryptomator/ui/convertvault/HubToPasswordConvertController.java
+++ b/src/main/java/org/cryptomator/ui/convertvault/HubToPasswordConvertController.java
@@ -15,6 +15,7 @@ import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.common.FxmlFile;
import org.cryptomator.ui.common.FxmlScene;
import org.cryptomator.ui.fxapp.FxApplicationWindows;
+import org.cryptomator.ui.keyloading.masterkeyfile.MasterkeyFileLoadingStrategy;
import org.cryptomator.ui.recoverykey.RecoveryKeyFactory;
import org.jetbrains.annotations.VisibleForTesting;
import org.slf4j.Logger;
@@ -108,6 +109,7 @@ public class HubToPasswordConvertController implements FxController {
.thenRunAsync(this::convertInternal, backgroundExecutorService) //
.whenCompleteAsync((result, exception) -> {
if (exception == null) {
+ vault.getVaultSettings().lastKnownKeyLoader.set(MasterkeyFileLoadingStrategy.SCHEME);
LOG.info("Conversion of vault {} succeeded.", vault.getPath());
window.setScene(successScene.get());
} else {
diff --git a/src/main/java/org/cryptomator/ui/dialogs/Dialogs.java b/src/main/java/org/cryptomator/ui/dialogs/Dialogs.java
index 5107fe740..837bea012 100644
--- a/src/main/java/org/cryptomator/ui/dialogs/Dialogs.java
+++ b/src/main/java/org/cryptomator/ui/dialogs/Dialogs.java
@@ -38,7 +38,7 @@ public class Dialogs {
.setMessageKey("removeVault.message") //
.setDescriptionKey("removeVault.description") //
.setIcon(FontAwesome5Icon.QUESTION) //
- .setOkButtonKey("removeVault.confirmBtn") //
+ .setOkButtonKey("generic.button.remove") //
.setCancelButtonKey("generic.button.cancel") //
.setOkAction(stage -> {
LOG.debug("Removing vault {}.", vault.getDisplayName());
@@ -54,7 +54,7 @@ public class Dialogs {
.setMessageKey("removeCert.message") //
.setDescriptionKey("removeCert.description") //
.setIcon(FontAwesome5Icon.QUESTION) //
- .setOkButtonKey("removeCert.confirmBtn") //
+ .setOkButtonKey("generic.button.remove") //
.setCancelButtonKey("generic.button.cancel") //
.setOkAction(stage -> {
settings.licenseKey.set(null);
diff --git a/src/main/java/org/cryptomator/ui/dialogs/SimpleDialog.java b/src/main/java/org/cryptomator/ui/dialogs/SimpleDialog.java
index 84d9e4f75..08f77849e 100644
--- a/src/main/java/org/cryptomator/ui/dialogs/SimpleDialog.java
+++ b/src/main/java/org/cryptomator/ui/dialogs/SimpleDialog.java
@@ -31,8 +31,9 @@ public class SimpleDialog {
FxmlLoaderFactory loaderFactory = FxmlLoaderFactory.forController( //
new SimpleDialogController(resolveText(builder.messageKey, null), //
resolveText(builder.descriptionKey, null), //
- builder.icon, resolveText(builder.okButtonKey, null), //
- resolveText(builder.cancelButtonKey, null), //
+ builder.icon, //
+ resolveText(builder.okButtonKey, null), //
+ builder.cancelButtonKey != null ? resolveText(builder.cancelButtonKey, null) : null, //
() -> builder.okAction.accept(dialogStage), //
() -> builder.cancelAction.accept(dialogStage)), //
Scene::new, builder.resourceBundle);
@@ -67,7 +68,6 @@ public class SimpleDialog {
private String descriptionKey;
private String okButtonKey;
private String cancelButtonKey;
-
private FontAwesome5Icon icon;
private Consumer okAction = Stage::close;
private Consumer cancelAction = Stage::close;
@@ -128,7 +128,6 @@ public class SimpleDialog {
Objects.requireNonNull(messageKey, "SimpleDialog messageKey must be set.");
Objects.requireNonNull(descriptionKey, "SimpleDialog descriptionKey must be set.");
Objects.requireNonNull(okButtonKey, "SimpleDialog okButtonKey must be set.");
- Objects.requireNonNull(cancelButtonKey, "SimpleDialog cancelButtonKey must be set.");
try {
return new SimpleDialog(this);
diff --git a/src/main/java/org/cryptomator/ui/dialogs/SimpleDialogController.java b/src/main/java/org/cryptomator/ui/dialogs/SimpleDialogController.java
index 0eee1b308..bbf590145 100644
--- a/src/main/java/org/cryptomator/ui/dialogs/SimpleDialogController.java
+++ b/src/main/java/org/cryptomator/ui/dialogs/SimpleDialogController.java
@@ -14,6 +14,7 @@ public class SimpleDialogController implements FxController {
private final String cancelButtonText;
private final Runnable okAction;
private final Runnable cancelAction;
+ private final boolean cancelButtonVisible;
public SimpleDialogController(String message, String description, FontAwesome5Icon icon, String okButtonText, String cancelButtonText, Runnable okAction, Runnable cancelAction) {
this.message = message;
@@ -23,6 +24,11 @@ public class SimpleDialogController implements FxController {
this.cancelButtonText = cancelButtonText;
this.okAction = okAction;
this.cancelAction = cancelAction;
+ this.cancelButtonVisible = cancelButtonText != null && !cancelButtonText.isEmpty();
+ }
+
+ public boolean isCancelButtonVisible() {
+ return cancelButtonVisible;
}
public String getMessage() {
diff --git a/src/main/java/org/cryptomator/ui/keyloading/KeyLoadingStrategy.java b/src/main/java/org/cryptomator/ui/keyloading/KeyLoadingStrategy.java
index f3f0aff8e..b9af0f4a3 100644
--- a/src/main/java/org/cryptomator/ui/keyloading/KeyLoadingStrategy.java
+++ b/src/main/java/org/cryptomator/ui/keyloading/KeyLoadingStrategy.java
@@ -3,6 +3,8 @@ package org.cryptomator.ui.keyloading;
import org.cryptomator.cryptolib.api.Masterkey;
import org.cryptomator.cryptolib.api.MasterkeyLoader;
import org.cryptomator.cryptolib.api.MasterkeyLoadingFailedException;
+import org.cryptomator.ui.keyloading.hub.HubKeyLoadingStrategy;
+import org.cryptomator.ui.keyloading.masterkeyfile.MasterkeyFileLoadingStrategy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -28,6 +30,33 @@ public interface KeyLoadingStrategy extends MasterkeyLoader {
@Override
Masterkey loadKey(URI keyId) throws MasterkeyLoadingFailedException;
+ /**
+ * Determines whether the provided key loader scheme corresponds to a Hub Vault.
+ *
+ * This method compares the {@code keyLoader} parameter with the known Hub Vault schemes
+ * {@link HubKeyLoadingStrategy#SCHEME_HUB_HTTP} and {@link HubKeyLoadingStrategy#SCHEME_HUB_HTTPS}.
+ *
+ * @param keyLoader A string representing the key loader scheme to be checked.
+ * @return {@code true} if the given key loader scheme represents a Hub Vault; {@code false} otherwise.
+ */
+ static boolean isHubVault(String keyLoader) {
+ return HubKeyLoadingStrategy.SCHEME_HUB_HTTP.equals(keyLoader) || HubKeyLoadingStrategy.SCHEME_HUB_HTTPS.equals(keyLoader);
+ }
+
+ /**
+ * Determines whether the provided key loader scheme corresponds to a Masterkey File Vault.
+ *
+ * This method checks if the {@code keyLoader} parameter matches the known Masterkey File Vault scheme
+ * {@link MasterkeyFileLoadingStrategy#SCHEME}.
+ *
+ *
+ * @param keyLoader A string representing the key loader scheme to be checked.
+ * @return {@code true} if the given key loader scheme represents a Masterkey File Vault; {@code false} otherwise.
+ */
+ static boolean isMasterkeyFileVault(String keyLoader) {
+ return MasterkeyFileLoadingStrategy.SCHEME.equals(keyLoader);
+ }
+
/**
* Allows the loader to try and recover from an exception thrown during the last attempt.
*
diff --git a/src/main/java/org/cryptomator/ui/keyloading/hub/ReceiveKeyController.java b/src/main/java/org/cryptomator/ui/keyloading/hub/ReceiveKeyController.java
index aa56a22e7..f94d882fa 100644
--- a/src/main/java/org/cryptomator/ui/keyloading/hub/ReceiveKeyController.java
+++ b/src/main/java/org/cryptomator/ui/keyloading/hub/ReceiveKeyController.java
@@ -165,6 +165,7 @@ public class ReceiveKeyController implements FxController {
var vaultKeyUri = hubConfig.URIs.API.resolve("vaults/" + vaultId + "/access-token");
var request = HttpRequest.newBuilder(vaultKeyUri) //
.header("Authorization", "Bearer " + bearerToken) //
+ .header("Hub-Device-ID", deviceId) //
.GET() //
.timeout(REQ_TIMEOUT) //
.build();
diff --git a/src/main/java/org/cryptomator/ui/mainwindow/MainWindowController.java b/src/main/java/org/cryptomator/ui/mainwindow/MainWindowController.java
index 13412dd27..18db5e5ac 100644
--- a/src/main/java/org/cryptomator/ui/mainwindow/MainWindowController.java
+++ b/src/main/java/org/cryptomator/ui/mainwindow/MainWindowController.java
@@ -19,9 +19,11 @@ import javafx.beans.property.ObjectProperty;
import javafx.beans.property.ReadOnlyBooleanProperty;
import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.fxml.FXML;
+import javafx.geometry.Rectangle2D;
import javafx.scene.layout.StackPane;
import javafx.stage.Screen;
import javafx.stage.Stage;
+import javafx.stage.WindowEvent;
@MainWindowScoped
public class MainWindowController implements FxController {
@@ -68,18 +70,15 @@ public class MainWindowController implements FxController {
int y = settings.windowYPosition.get();
int width = settings.windowWidth.get();
int height = settings.windowHeight.get();
- if (windowPositionSaved(x, y, width, height) ) {
- if(isWithinDisplayBounds(x, y, width, height)) { //use stored window position
- window.setX(x);
- window.setY(y);
- window.setWidth(Math.clamp(width, window.getMinWidth(), window.getMaxWidth()));
- window.setHeight(Math.clamp(height, window.getMinHeight(), window.getMaxHeight()));
- } else if(isWithinDisplayBounds((int) window.getX(), (int) window.getY(), width, height)) { //just reset position of upper left corner, keep window size
- window.setWidth(Math.clamp(width, window.getMinWidth(), window.getMaxWidth()));
- window.setHeight(Math.clamp(height, window.getMinHeight(), window.getMaxHeight()));
- } //else reset window completely
+ if (windowPositionSaved(x, y, width, height)) {
+ window.setX(x);
+ window.setY(y);
+ window.setWidth(Math.clamp(width, window.getMinWidth(), window.getMaxWidth()));
+ window.setHeight(Math.clamp(height, window.getMinHeight(), window.getMaxHeight()));
}
+ window.setOnShowing(this::checkDisplayBounds);
+
settings.windowXPosition.bind(window.xProperty());
settings.windowYPosition.bind(window.yProperty());
settings.windowWidth.bind(window.widthProperty());
@@ -90,6 +89,39 @@ public class MainWindowController implements FxController {
return x != 0 || y != 0 || width != 0 || height != 0;
}
+ private void checkDisplayBounds(WindowEvent windowEvent) {
+ int x = settings.windowXPosition.get();
+ int y = settings.windowYPosition.get();
+ int width = settings.windowWidth.get();
+ int height = settings.windowHeight.get();
+
+ // Minimizing a window in Windows and closing it could result in an out of bounds position at (x, y) = (-32000, -32000)
+ // See https://devblogs.microsoft.com/oldnewthing/20041028-00/?p=37453
+ // If the position is (-32000, -32000), restore to the last saved position
+ if (window.getX() == -32000 && window.getY() == -32000) {
+ window.setX(x);
+ window.setY(y);
+ window.setWidth(width);
+ window.setHeight(height);
+ }
+
+ Rectangle2D primaryScreenBounds = Screen.getPrimary().getBounds();
+ if (!isWithinDisplayBounds(x, y, width, height)) { //use stored window position
+ LOG.debug("Resetting window position due to insufficient screen overlap");
+ var centeredX = (primaryScreenBounds.getWidth() - window.getMinWidth()) / 2;
+ var centeredY = (primaryScreenBounds.getHeight() - window.getMinHeight()) / 2;
+ //check if we can keep width and height
+ if (isWithinDisplayBounds((int) centeredX, (int) centeredY, width, height)) {
+ //if so, keep window size
+ window.setWidth(Math.clamp(width, window.getMinWidth(), window.getMaxWidth()));
+ window.setHeight(Math.clamp(height, window.getMinHeight(), window.getMaxHeight()));
+ }
+ //reset position of upper left corner
+ window.setX(centeredX);
+ window.setY(centeredY);
+ }
+ }
+
private boolean isWithinDisplayBounds(int x, int y, int width, int height) {
// define a rect which is inset on all sides from the window's rect:
final int shrinkedX = x + 20; // 20px left
diff --git a/src/main/java/org/cryptomator/ui/sharevault/ShareVaultController.java b/src/main/java/org/cryptomator/ui/sharevault/ShareVaultController.java
index 63230cbbf..859c9e38d 100644
--- a/src/main/java/org/cryptomator/ui/sharevault/ShareVaultController.java
+++ b/src/main/java/org/cryptomator/ui/sharevault/ShareVaultController.java
@@ -3,7 +3,7 @@ package org.cryptomator.ui.sharevault;
import dagger.Lazy;
import org.cryptomator.common.vaults.Vault;
import org.cryptomator.ui.common.FxController;
-import org.cryptomator.ui.keyloading.hub.HubKeyLoadingStrategy;
+import org.cryptomator.ui.keyloading.KeyLoadingStrategy;
import javax.inject.Inject;
import javafx.application.Application;
@@ -33,8 +33,7 @@ public class ShareVaultController implements FxController {
this.window = window;
this.application = application;
this.vault = vault;
- var vaultScheme = vault.getVaultConfigCache().getUnchecked().getKeyId().getScheme();
- this.hubVault = (vaultScheme.equals(HubKeyLoadingStrategy.SCHEME_HUB_HTTP) || vaultScheme.equals(HubKeyLoadingStrategy.SCHEME_HUB_HTTPS));
+ this.hubVault = KeyLoadingStrategy.isHubVault(vault.getVaultSettings().lastKnownKeyLoader.get());
}
@FXML
diff --git a/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsController.java b/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsController.java
index 78d228995..154eb30dd 100644
--- a/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsController.java
+++ b/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsController.java
@@ -3,6 +3,7 @@ package org.cryptomator.ui.vaultoptions;
import org.cryptomator.common.vaults.Vault;
import org.cryptomator.common.vaults.VaultState;
import org.cryptomator.ui.common.FxController;
+import org.cryptomator.ui.keyloading.KeyLoadingStrategy;
import org.cryptomator.ui.keyloading.hub.HubKeyLoadingStrategy;
import org.cryptomator.ui.keyloading.masterkeyfile.MasterkeyFileLoadingStrategy;
import org.slf4j.Logger;
@@ -42,11 +43,11 @@ public class VaultOptionsController implements FxController {
window.setOnShowing(this::windowWillAppear);
selectedTabProperty.addListener(observable -> this.selectChosenTab());
tabPane.getSelectionModel().selectedItemProperty().addListener(observable -> this.selectedTabChanged());
- var vaultScheme = vault.getVaultConfigCache().getUnchecked().getKeyId().getScheme();
- if(!vaultScheme.equals(MasterkeyFileLoadingStrategy.SCHEME)){
+ var vaultKeyLoader = vault.getVaultSettings().lastKnownKeyLoader.get();
+ if(!KeyLoadingStrategy.isMasterkeyFileVault(vaultKeyLoader)){
tabPane.getTabs().remove(keyTab);
}
- if(!(vaultScheme.equals(HubKeyLoadingStrategy.SCHEME_HUB_HTTP) || vaultScheme.equals(HubKeyLoadingStrategy.SCHEME_HUB_HTTPS))){
+ if(!KeyLoadingStrategy.isHubVault(vaultKeyLoader)){
tabPane.getTabs().remove(hubTab);
}
diff --git a/src/main/resources/css/dark_theme.css b/src/main/resources/css/dark_theme.css
index abb6efe57..4d3db3968 100644
--- a/src/main/resources/css/dark_theme.css
+++ b/src/main/resources/css/dark_theme.css
@@ -359,6 +359,12 @@
-fx-background-color: PRIMARY;
}
+.notification-debug:hover .notification-label,
+.notification-update:hover .notification-label,
+.notification-support:hover .notification-label {
+ -fx-underline:true;
+}
+
/*******************************************************************************
* *
* ScrollBar *
diff --git a/src/main/resources/css/light_theme.css b/src/main/resources/css/light_theme.css
index b4376eaf5..dec0a33de 100644
--- a/src/main/resources/css/light_theme.css
+++ b/src/main/resources/css/light_theme.css
@@ -397,6 +397,12 @@
-fx-background-color: PRIMARY;
}
+.notification-debug:hover .notification-label,
+.notification-update:hover .notification-label,
+.notification-support:hover .notification-label {
+ -fx-underline:true;
+}
+
/*******************************************************************************
* *
* ScrollBar *
diff --git a/src/main/resources/fxml/simple_dialog.fxml b/src/main/resources/fxml/simple_dialog.fxml
index 32ad63abf..0e9b01776 100644
--- a/src/main/resources/fxml/simple_dialog.fxml
+++ b/src/main/resources/fxml/simple_dialog.fxml
@@ -1,16 +1,16 @@
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
+
diff --git a/src/main/resources/i18n/strings.properties b/src/main/resources/i18n/strings.properties
index 5cf23ebce..59cc81742 100644
--- a/src/main/resources/i18n/strings.properties
+++ b/src/main/resources/i18n/strings.properties
@@ -108,7 +108,6 @@ addvaultwizard.success.unlockNow=Unlock Now
removeVault.title=Remove "%s"
removeVault.message=Remove vault?
removeVault.description=This will only make Cryptomator forget about this vault. You can add it again. No encrypted files will be deleted from your hard drive.
-removeVault.confirmBtn=Remove Vault
# Change Password
changepassword.title=Change Password
@@ -285,7 +284,7 @@ preferences.title=Preferences
## General
preferences.general=General
preferences.general.startHidden=Hide window when starting Cryptomator
-preferences.general.autoCloseVaults=Lock open vaults automatically when quitting application
+preferences.general.autoCloseVaults=Lock vaults without asking when quitting application
preferences.general.debugLogging=Enable debug logging
preferences.general.debugDirectory=Reveal log files
preferences.general.autoStart=Launch Cryptomator on system start
diff --git a/src/test/java/org/cryptomator/ui/addvaultwizard/ReadMeGeneratorTest.java b/src/test/java/org/cryptomator/ui/addvaultwizard/ReadMeGeneratorTest.java
index 97f02aee1..10451daa2 100644
--- a/src/test/java/org/cryptomator/ui/addvaultwizard/ReadMeGeneratorTest.java
+++ b/src/test/java/org/cryptomator/ui/addvaultwizard/ReadMeGeneratorTest.java
@@ -15,8 +15,8 @@ public class ReadMeGeneratorTest {
@ParameterizedTest
@CsvSource({ //
"test,test", //
- "t\u00E4st,t\\u228st", //
- "t\uD83D\uDE09st,t\\u55357\\u56841st", //
+ "t\u00E4st,t\\'E4st", //
+ "t\uD83D\uDE09st,t\\uc1\\u55357\\uc1\\u56841st", //
})
public void testEscapeNonAsciiChars(String input, String expectedResult) {
ReadmeGenerator readmeGenerator = new ReadmeGenerator(null);
@@ -40,7 +40,7 @@ public class ReadMeGeneratorTest {
MatcherAssert.assertThat(result, CoreMatchers.startsWith("{\\rtf1\\fbidis\\ansi\\uc0\\fs32"));
MatcherAssert.assertThat(result, CoreMatchers.containsString("{\\sa80 Dear User,}\\par"));
MatcherAssert.assertThat(result, CoreMatchers.containsString("{\\sa80 \\b please don't touch the \"d\" directory.}\\par "));
- MatcherAssert.assertThat(result, CoreMatchers.containsString("{\\sa80 Thank you for your cooperation \\u55357\\u56841}\\par"));
+ MatcherAssert.assertThat(result, CoreMatchers.containsString("{\\sa80 Thank you for your cooperation \\uc1\\u55357\\uc1\\u56841}\\par"));
MatcherAssert.assertThat(result, CoreMatchers.endsWith("}"));
}