diff --git a/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettings.java b/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettings.java index 1db67d4d5..132df8245 100644 --- a/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettings.java +++ b/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettings.java @@ -30,8 +30,8 @@ public class VaultSettings { public static final String DEFAULT_MOUNT_FLAGS = ""; public static final int DEFAULT_MAX_CLEARTEXT_FILENAME_LENGTH = -1; public static final WhenUnlocked DEFAULT_ACTION_AFTER_UNLOCK = WhenUnlocked.ASK; - public static final boolean DEFAULT_LOCK_AFTER_TIME = false; - public static final int DEFAULT_LOCK_TIME_IN_MINUTES = 30; + public static final boolean DEFAULT_AUTOLOCK_WHEN_IDLE = false; + public static final int DEFAULT_AUTOLOCK_IDLE_SECONDS = 30 * 60; private static final Random RNG = new Random(); @@ -47,8 +47,8 @@ public class VaultSettings { private final StringProperty mountFlags = new SimpleStringProperty(DEFAULT_MOUNT_FLAGS); private final IntegerProperty maxCleartextFilenameLength = new SimpleIntegerProperty(DEFAULT_MAX_CLEARTEXT_FILENAME_LENGTH); private final ObjectProperty actionAfterUnlock = new SimpleObjectProperty<>(DEFAULT_ACTION_AFTER_UNLOCK); - private final BooleanProperty lockAfterTime = new SimpleBooleanProperty(DEFAULT_LOCK_AFTER_TIME); - private final IntegerProperty lockTimeInMinutes = new SimpleIntegerProperty(DEFAULT_LOCK_TIME_IN_MINUTES); + private final BooleanProperty autoLockWhenIdle = new SimpleBooleanProperty(DEFAULT_AUTOLOCK_WHEN_IDLE); + private final IntegerProperty autoLockIdleSeconds = new SimpleIntegerProperty(DEFAULT_AUTOLOCK_IDLE_SECONDS); private final StringBinding mountName; public VaultSettings(String id) { @@ -57,7 +57,7 @@ public class VaultSettings { } Observable[] observables() { - return new Observable[]{path, displayName, winDriveLetter, unlockAfterStartup, revealAfterMount, useCustomMountPath, customMountPath, usesReadOnlyMode, mountFlags, maxCleartextFilenameLength, actionAfterUnlock, lockAfterTime, lockTimeInMinutes}; + return new Observable[]{path, displayName, winDriveLetter, unlockAfterStartup, revealAfterMount, useCustomMountPath, customMountPath, usesReadOnlyMode, mountFlags, maxCleartextFilenameLength, actionAfterUnlock, autoLockWhenIdle, autoLockIdleSeconds}; } public static VaultSettings withRandomId() { @@ -158,12 +158,12 @@ public class VaultSettings { return actionAfterUnlock.get(); } - public BooleanProperty lockAfterTime() { - return lockAfterTime; + public BooleanProperty autoLockWhenIdle() { + return autoLockWhenIdle; } - public IntegerProperty lockTimeInMinutes() { - return lockTimeInMinutes; + public IntegerProperty autoLockIdleSeconds() { + return autoLockIdleSeconds; } /* Hashcode/Equals */ diff --git a/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettingsJsonAdapter.java b/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettingsJsonAdapter.java index 26aa3d51c..0cf92a48b 100644 --- a/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettingsJsonAdapter.java +++ b/main/commons/src/main/java/org/cryptomator/common/settings/VaultSettingsJsonAdapter.java @@ -31,8 +31,8 @@ class VaultSettingsJsonAdapter { out.name("mountFlags").value(value.mountFlags().get()); out.name("maxCleartextFilenameLength").value(value.maxCleartextFilenameLength().get()); out.name("actionAfterUnlock").value(value.actionAfterUnlock().get().name()); - out.name("lockAfterTime").value(value.lockAfterTime().get()); - out.name("lockTimeInMinutes").value(value.lockTimeInMinutes().get()); + out.name("autoLockWhenIdle").value(value.autoLockWhenIdle().get()); + out.name("autoLockIdleSeconds").value(value.autoLockIdleSeconds().get()); out.endObject(); } @@ -50,8 +50,8 @@ class VaultSettingsJsonAdapter { String mountFlags = VaultSettings.DEFAULT_MOUNT_FLAGS; int maxCleartextFilenameLength = VaultSettings.DEFAULT_MAX_CLEARTEXT_FILENAME_LENGTH; WhenUnlocked actionAfterUnlock = VaultSettings.DEFAULT_ACTION_AFTER_UNLOCK; - boolean lockAfterTime = VaultSettings.DEFAULT_LOCK_AFTER_TIME; - int lockTimeInMinutes = VaultSettings.DEFAULT_LOCK_TIME_IN_MINUTES; + boolean autoLockWhenIdle = VaultSettings.DEFAULT_AUTOLOCK_WHEN_IDLE; + int autoLockIdleSeconds = VaultSettings.DEFAULT_AUTOLOCK_IDLE_SECONDS; in.beginObject(); while (in.hasNext()) { @@ -70,8 +70,8 @@ class VaultSettingsJsonAdapter { case "mountFlags" -> mountFlags = in.nextString(); case "maxCleartextFilenameLength" -> maxCleartextFilenameLength = in.nextInt(); case "actionAfterUnlock" -> actionAfterUnlock = parseActionAfterUnlock(in.nextString()); - case "lockAfterTime" -> lockAfterTime = in.nextBoolean(); - case "lockTimeInMinutes" -> lockTimeInMinutes = in.nextInt(); + case "autoLockWhenIdle" -> autoLockWhenIdle = in.nextBoolean(); + case "autoLockIdleSeconds" -> autoLockIdleSeconds = in.nextInt(); default -> { LOG.warn("Unsupported vault setting found in JSON: " + name); in.skipValue(); @@ -96,8 +96,8 @@ class VaultSettingsJsonAdapter { vaultSettings.mountFlags().set(mountFlags); vaultSettings.maxCleartextFilenameLength().set(maxCleartextFilenameLength); vaultSettings.actionAfterUnlock().set(actionAfterUnlock); - vaultSettings.lockAfterTime().set(lockAfterTime); - vaultSettings.lockTimeInMinutes().set(lockTimeInMinutes); + vaultSettings.autoLockWhenIdle().set(autoLockWhenIdle); + vaultSettings.autoLockIdleSeconds().set(autoLockIdleSeconds); return vaultSettings; } diff --git a/main/commons/src/main/java/org/cryptomator/common/vaults/AutoLocker.java b/main/commons/src/main/java/org/cryptomator/common/vaults/AutoLocker.java index dcaafdb13..da584086d 100644 --- a/main/commons/src/main/java/org/cryptomator/common/vaults/AutoLocker.java +++ b/main/commons/src/main/java/org/cryptomator/common/vaults/AutoLocker.java @@ -7,7 +7,6 @@ import javax.inject.Inject; import javax.inject.Singleton; import javafx.collections.ObservableList; import java.time.Instant; -import java.time.temporal.ChronoUnit; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; @@ -48,11 +47,10 @@ public class AutoLocker { private boolean exceedsIdleTime(Vault vault) { assert vault.isUnlocked(); // TODO: shouldn't we read these properties from within FX Application Thread? - if (vault.getVaultSettings().lockAfterTime().get()) { - int maxIdleMinutes = vault.getVaultSettings().lockTimeInMinutes().get(); - var idleSince = vault.getStats().getLastActivity(); - var threshold = idleSince.plus(maxIdleMinutes, ChronoUnit.MINUTES); - return threshold.isBefore(Instant.now()); + if (vault.getVaultSettings().autoLockWhenIdle().get()) { + int maxIdleSeconds = vault.getVaultSettings().autoLockIdleSeconds().get(); + var deadline = vault.getStats().getLastActivity().plusSeconds(maxIdleSeconds); + return deadline.isBefore(Instant.now()); } else { return false; } diff --git a/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/AutoLockVaultOptionsController.java b/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/AutoLockVaultOptionsController.java index e8e5ca5fb..1bb74690f 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/AutoLockVaultOptionsController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/AutoLockVaultOptionsController.java @@ -8,12 +8,13 @@ import javax.inject.Inject; import javafx.beans.binding.Bindings; import javafx.fxml.FXML; import javafx.scene.control.CheckBox; -import javafx.util.converter.NumberStringConverter; +import javafx.util.StringConverter; @VaultOptionsScoped public class AutoLockVaultOptionsController implements FxController { private final Vault vault; + public CheckBox lockAfterTimeCheckbox; public NumericTextField lockTimeInMinutesTextField; @@ -24,8 +25,27 @@ public class AutoLockVaultOptionsController implements FxController { @FXML public void initialize() { - lockAfterTimeCheckbox.selectedProperty().bindBidirectional(vault.getVaultSettings().lockAfterTime()); - Bindings.bindBidirectional(lockTimeInMinutesTextField.textProperty(), vault.getVaultSettings().lockTimeInMinutes(), new NumberStringConverter()); + lockAfterTimeCheckbox.selectedProperty().bindBidirectional(vault.getVaultSettings().autoLockWhenIdle()); + Bindings.bindBidirectional(lockTimeInMinutesTextField.textProperty(), vault.getVaultSettings().autoLockIdleSeconds(), new IdleTimeSecondsConverter()); + } + + private static class IdleTimeSecondsConverter extends StringConverter { + + @Override + public String toString(Number seconds) { + int minutes = seconds.intValue() / 60; // int-truncate + return Integer.toString(minutes); + } + + @Override + public Number fromString(String string) { + try { + int minutes = Integer.valueOf(string); + return minutes * 60; + } catch (NumberFormatException e) { + return 0; + } + } } }