Sebastian Stenzel 5 år sedan
förälder
incheckning
86906d0049

+ 11 - 1
main/commons/src/main/java/org/cryptomator/common/settings/VaultSettings.java

@@ -35,6 +35,7 @@ public class VaultSettings {
 	public static final boolean DEFAULT_USES_READONLY_MODE = false;
 	public static final String DEFAULT_MOUNT_FLAGS = "";
 	public static final int DEFAULT_FILENAME_LENGTH_LIMIT = -1;
+	public static final WhenUnlocked DEFAULT_ACTION_AFTER_UNLOCK = WhenUnlocked.ASK;
 	
 	private static final Random RNG = new Random(); 
 
@@ -49,6 +50,7 @@ public class VaultSettings {
 	private final BooleanProperty usesReadOnlyMode = new SimpleBooleanProperty(DEFAULT_USES_READONLY_MODE);
 	private final StringProperty mountFlags = new SimpleStringProperty(DEFAULT_MOUNT_FLAGS);
 	private final IntegerProperty filenameLengthLimit = new SimpleIntegerProperty(DEFAULT_FILENAME_LENGTH_LIMIT);
+	private final ObjectProperty<WhenUnlocked> actionAfterUnlock = new SimpleObjectProperty<>(DEFAULT_ACTION_AFTER_UNLOCK);
 
 	public VaultSettings(String id) {
 		this.id = Objects.requireNonNull(id);
@@ -57,7 +59,7 @@ public class VaultSettings {
 	}
 
 	Observable[] observables() {
-		return new Observable[]{path, mountName, winDriveLetter, unlockAfterStartup, revealAfterMount, usesIndividualMountPath, individualMountPath, usesReadOnlyMode, mountFlags, filenameLengthLimit};
+		return new Observable[]{path, mountName, winDriveLetter, unlockAfterStartup, revealAfterMount, useCustomMountPath, customMountPath, usesReadOnlyMode, mountFlags, filenameLengthLimit, actionAfterUnlock};
 	}
 
 	private void deriveMountNameFromPath(Path path) {
@@ -149,6 +151,14 @@ public class VaultSettings {
 		return filenameLengthLimit;
 	}
 
+	public ObjectProperty<WhenUnlocked> actionAfterUnlock() {
+		return actionAfterUnlock;
+	}
+
+	public WhenUnlocked getActionAfterUnlock() {
+		return actionAfterUnlock.get();
+	}
+
 	/* Hashcode/Equals */
 
 	@Override

+ 15 - 0
main/commons/src/main/java/org/cryptomator/common/settings/VaultSettingsJsonAdapter.java

@@ -30,6 +30,7 @@ class VaultSettingsJsonAdapter {
 		out.name("usesReadOnlyMode").value(value.usesReadOnlyMode().get());
 		out.name("mountFlags").value(value.mountFlags().get());
 		out.name("filenameLengthLimit").value(value.filenameLengthLimit().get());
+		out.name("actionAfterUnlock").value(value.actionAfterUnlock().get().name());
 		out.endObject();
 	}
 
@@ -45,6 +46,7 @@ class VaultSettingsJsonAdapter {
 		boolean usesReadOnlyMode = VaultSettings.DEFAULT_USES_READONLY_MODE;
 		String mountFlags = VaultSettings.DEFAULT_MOUNT_FLAGS;
 		int filenameLengthLimit = VaultSettings.DEFAULT_FILENAME_LENGTH_LIMIT;
+		WhenUnlocked actionAfterUnlock = VaultSettings.DEFAULT_ACTION_AFTER_UNLOCK;
 
 		in.beginObject();
 		while (in.hasNext()) {
@@ -85,6 +87,9 @@ class VaultSettingsJsonAdapter {
 				case "filenameLengthLimit":
 					filenameLengthLimit = in.nextInt();
 					break;
+				case "actionAfterUnlock":
+					actionAfterUnlock = parseActionAfterUnlock(in.nextString());
+					break;
 				default:
 					LOG.warn("Unsupported vault setting found in JSON: " + name);
 					in.skipValue();
@@ -104,7 +109,17 @@ class VaultSettingsJsonAdapter {
 		vaultSettings.usesReadOnlyMode().set(usesReadOnlyMode);
 		vaultSettings.mountFlags().set(mountFlags);
 		vaultSettings.filenameLengthLimit().set(filenameLengthLimit);
+		vaultSettings.actionAfterUnlock().set(actionAfterUnlock);
 		return vaultSettings;
 	}
 
+	private WhenUnlocked parseActionAfterUnlock(String actionAfterUnlockName) {
+		try {
+			return WhenUnlocked.valueOf(actionAfterUnlockName.toUpperCase());
+		} catch (IllegalArgumentException e) {
+			LOG.warn("Invalid action after unlock {}. Defaulting to {}.", actionAfterUnlockName, VaultSettings.DEFAULT_ACTION_AFTER_UNLOCK);
+			return VaultSettings.DEFAULT_ACTION_AFTER_UNLOCK;
+		}
+	}
+
 }

+ 17 - 0
main/commons/src/main/java/org/cryptomator/common/settings/WhenUnlocked.java

@@ -0,0 +1,17 @@
+package org.cryptomator.common.settings;
+
+public enum WhenUnlocked {
+	IGNORE("vaultOptions.general.actionAfterUnlock.ignore"),
+	REVEAL("vaultOptions.general.actionAfterUnlock.reveal"),
+	ASK("vaultOptions.general.actionAfterUnlock.ask");
+
+	private String displayName;
+
+	WhenUnlocked(String displayName) {
+		this.displayName = displayName;
+	}
+
+	public String getDisplayName() {
+		return displayName;
+	}
+}

+ 10 - 0
main/ui/src/main/java/org/cryptomator/ui/unlock/UnlockSuccessController.java

@@ -7,8 +7,10 @@ import javafx.beans.property.SimpleBooleanProperty;
 import javafx.beans.property.SimpleObjectProperty;
 import javafx.concurrent.Task;
 import javafx.fxml.FXML;
+import javafx.scene.control.CheckBox;
 import javafx.scene.control.ContentDisplay;
 import javafx.stage.Stage;
+import org.cryptomator.common.settings.WhenUnlocked;
 import org.cryptomator.common.vaults.Vault;
 import org.cryptomator.ui.common.FxController;
 import org.cryptomator.ui.common.VaultService;
@@ -29,6 +31,8 @@ public class UnlockSuccessController implements FxController {
 	private final VaultService vaultService;
 	private final ObjectProperty<ContentDisplay> revealButtonState;
 	private final BooleanProperty revealButtonDisabled;
+	
+	public CheckBox rememberChoiceCheckbox;
 
 	@Inject
 	public UnlockSuccessController(@UnlockWindow Stage window, @UnlockWindow Vault vault, ExecutorService executor, VaultService vaultService) {
@@ -44,6 +48,9 @@ public class UnlockSuccessController implements FxController {
 	public void close() {
 		LOG.trace("UnlockSuccessController.close()");
 		window.close();
+		if (rememberChoiceCheckbox.isSelected()) {
+			vault.getVaultSettings().actionAfterUnlock().setValue(WhenUnlocked.IGNORE);
+		}
 	}
 
 	@FXML
@@ -64,6 +71,9 @@ public class UnlockSuccessController implements FxController {
 			revealButtonDisabled.set(false);
 		});
 		executor.execute(revealTask);
+		if (rememberChoiceCheckbox.isSelected()) {
+			vault.getVaultSettings().actionAfterUnlock().setValue(WhenUnlocked.REVEAL);
+		}
 	}
 
 	/* Getter/Setter */

+ 7 - 3
main/ui/src/main/java/org/cryptomator/ui/unlock/UnlockWorkflow.java

@@ -5,6 +5,7 @@ import javafx.application.Platform;
 import javafx.concurrent.Task;
 import javafx.scene.Scene;
 import javafx.stage.Stage;
+import org.cryptomator.common.settings.WhenUnlocked;
 import org.cryptomator.common.vaults.Vault;
 import org.cryptomator.common.vaults.VaultState;
 import org.cryptomator.common.vaults.Volume;
@@ -121,9 +122,12 @@ public class UnlockWorkflow extends Task<Boolean> {
 		if (savePassword.get()) {
 			savePasswordToSystemkeychain();
 		}
-		Platform.runLater(() -> {
-			window.setScene(successScene.get()); // TODO only if enabled (see issue #1083)
-		});
+		if (vault.getVaultSettings().actionAfterUnlock().get() == WhenUnlocked.ASK) {
+			Platform.runLater(() -> {
+				window.setScene(successScene.get());
+				window.show();
+			});
+		}
 	}
 
 	private void savePasswordToSystemkeychain() {

+ 33 - 1
main/ui/src/main/java/org/cryptomator/ui/vaultoptions/GeneralVaultOptionsController.java

@@ -2,24 +2,56 @@ package org.cryptomator.ui.vaultoptions;
 
 import javafx.fxml.FXML;
 import javafx.scene.control.CheckBox;
+import javafx.scene.control.ChoiceBox;
+import javafx.util.StringConverter;
+import org.cryptomator.common.settings.UiTheme;
+import org.cryptomator.common.settings.WhenUnlocked;
 import org.cryptomator.common.vaults.Vault;
 import org.cryptomator.ui.common.FxController;
 
 import javax.inject.Inject;
+import java.util.ResourceBundle;
 
 @VaultOptionsScoped
 public class GeneralVaultOptionsController implements FxController {
 
 	private final Vault vault;
+	private final ResourceBundle resourceBundle;
+
 	public CheckBox unlockOnStartupCheckbox;
+	public ChoiceBox<WhenUnlocked> actionAfterUnlockChoiceBox;
 
 	@Inject
-	GeneralVaultOptionsController(@VaultOptionsWindow Vault vault) {
+	GeneralVaultOptionsController(@VaultOptionsWindow Vault vault, ResourceBundle resourceBundle) {
 		this.vault = vault;
+		this.resourceBundle = resourceBundle;
 	}
 
 	@FXML
 	public void initialize() {
 		unlockOnStartupCheckbox.selectedProperty().bindBidirectional(vault.getVaultSettings().unlockAfterStartup());
+		actionAfterUnlockChoiceBox.getItems().addAll(WhenUnlocked.values());
+		actionAfterUnlockChoiceBox.valueProperty().bindBidirectional(vault.getVaultSettings().actionAfterUnlock());
+		actionAfterUnlockChoiceBox.setConverter(new WhenUnlockedConverter(resourceBundle));
 	}
+
+	private static class WhenUnlockedConverter extends StringConverter<WhenUnlocked> {
+		
+		private final ResourceBundle resourceBundle;
+
+		public WhenUnlockedConverter(ResourceBundle resourceBundle) {
+			this.resourceBundle = resourceBundle;
+		}
+
+		@Override
+		public String toString(WhenUnlocked obj) {
+			return resourceBundle.getString(obj.getDisplayName());
+		}
+
+		@Override
+		public WhenUnlocked fromString(String string) {
+			throw new UnsupportedOperationException();
+		}
+	}
+
 }

+ 5 - 1
main/ui/src/main/resources/fxml/unlock_success.fxml

@@ -10,6 +10,7 @@
 <?import javafx.scene.shape.Circle?>
 <?import org.cryptomator.ui.controls.FontAwesome5IconView?>
 <?import org.cryptomator.ui.controls.FormattedLabel?>
+<?import javafx.scene.control.CheckBox?>
 <VBox xmlns="http://javafx.com/javafx"
 	  xmlns:fx="http://javafx.com/fxml"
 	  fx:controller="org.cryptomator.ui.unlock.UnlockSuccessController"
@@ -26,7 +27,10 @@
 				<Circle styleClass="glyph-icon-primary" radius="24"/>
 				<FontAwesome5IconView styleClass="glyph-icon-white" glyph="CHECK" glyphSize="24"/>
 			</StackPane>
-			<FormattedLabel format="%unlock.success.message" arg1="${controller.vault.displayableName}" wrapText="true" HBox.hgrow="ALWAYS"/>
+			<VBox spacing="6">
+				<FormattedLabel format="%unlock.success.message" arg1="${controller.vault.displayableName}" wrapText="true" HBox.hgrow="ALWAYS"/>
+				<CheckBox text="%unlock.success.rememberChoice" fx:id="rememberChoiceCheckbox"/>
+			</VBox>
 		</HBox>
 
 		<VBox alignment="BOTTOM_CENTER" VBox.vgrow="ALWAYS">

+ 8 - 0
main/ui/src/main/resources/fxml/vault_options_general.fxml

@@ -3,6 +3,9 @@
 <?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?>
 <VBox xmlns="http://javafx.com/javafx"
 	  xmlns:fx="http://javafx.com/fxml"
 	  fx:controller="org.cryptomator.ui.vaultoptions.GeneralVaultOptionsController"
@@ -12,5 +15,10 @@
 	</padding>
 	<children>
 		<CheckBox text="%vaultOptions.general.unlockAfterStartup" fx:id="unlockOnStartupCheckbox"/>
+
+		<HBox spacing="6" alignment="CENTER_LEFT">
+			<Label text="%vaultOptions.general.actionAfterUnlock"/>
+			<ChoiceBox fx:id="actionAfterUnlockChoiceBox"/>
+		</HBox>
 	</children>
 </VBox>

+ 5 - 0
main/ui/src/main/resources/i18n/strings.properties

@@ -96,6 +96,7 @@ unlock.savePassword=Save Password
 unlock.unlockBtn=Unlock
 ## Success
 unlock.success.message=Unlocked "%s" successfully! Your vault is now accessible.
+unlock.success.rememberChoice=Remember choice, don't show this again
 unlock.success.revealBtn=Reveal Vault
 ## Invalid Mount Point
 unlock.error.invalidMountPoint=Mount point is not an empty directory: %s
@@ -206,6 +207,10 @@ wrongFileAlert.link=For further assistance, visit
 ## General
 vaultOptions.general=General
 vaultOptions.general.unlockAfterStartup=Unlock vault when starting Cryptomator
+vaultOptions.general.actionAfterUnlock=After successful unlock
+vaultOptions.general.actionAfterUnlock.ignore=Do nothing
+vaultOptions.general.actionAfterUnlock.reveal=Reveal Drive
+vaultOptions.general.actionAfterUnlock.ask=Ask
 ## Mount
 vaultOptions.mount=Mounting
 vaultOptions.mount.readonly=Read-Only