Removed "Mount after unlock" option. Mounting/unmounting no longer visible to the user, but merged with unlocking/locking.

This commit is contained in:
Sebastian Stenzel
2018-05-14 21:37:38 +02:00
parent b0ab46b7b6
commit d53af61b58
13 changed files with 107 additions and 256 deletions

View File

@@ -26,7 +26,6 @@ import javafx.beans.property.StringProperty;
public class VaultSettings {
public static final boolean DEFAULT_UNLOCK_AFTER_STARTUP = false;
public static final boolean DEFAULT_MOUNT_AFTER_UNLOCK = true;
public static final boolean DEFAULT_REAVEAL_AFTER_MOUNT = true;
public static final boolean DEFAULT_USES_INDIVIDUAL_MOUNTPATH = false;
@@ -35,7 +34,6 @@ public class VaultSettings {
private final StringProperty mountName = new SimpleStringProperty();
private final StringProperty winDriveLetter = new SimpleStringProperty();
private final BooleanProperty unlockAfterStartup = new SimpleBooleanProperty(DEFAULT_UNLOCK_AFTER_STARTUP);
private final BooleanProperty mountAfterUnlock = new SimpleBooleanProperty(DEFAULT_MOUNT_AFTER_UNLOCK);
private final BooleanProperty revealAfterMount = new SimpleBooleanProperty(DEFAULT_REAVEAL_AFTER_MOUNT);
private final BooleanProperty usesIndividualMountPath = new SimpleBooleanProperty(DEFAULT_USES_INDIVIDUAL_MOUNTPATH);
private final StringProperty individualMountPath = new SimpleStringProperty();
@@ -47,7 +45,7 @@ public class VaultSettings {
}
Observable[] observables() {
return new Observable[]{path, mountName, winDriveLetter, unlockAfterStartup, mountAfterUnlock, revealAfterMount, usesIndividualMountPath, individualMountPath};
return new Observable[]{path, mountName, winDriveLetter, unlockAfterStartup, revealAfterMount, usesIndividualMountPath, individualMountPath};
}
private void deriveMountNameFromPath(Path path) {
@@ -118,10 +116,6 @@ public class VaultSettings {
return unlockAfterStartup;
}
public BooleanProperty mountAfterUnlock() {
return mountAfterUnlock;
}
public BooleanProperty revealAfterMount() {
return revealAfterMount;
}

View File

@@ -25,7 +25,6 @@ class VaultSettingsJsonAdapter {
out.name("mountName").value(value.mountName().get());
out.name("winDriveLetter").value(value.winDriveLetter().get());
out.name("unlockAfterStartup").value(value.unlockAfterStartup().get());
out.name("mountAfterUnlock").value(value.mountAfterUnlock().get());
out.name("revealAfterMount").value(value.revealAfterMount().get());
out.name("usesIndividualMountPath").value(value.usesIndividualMountPath().get());
//TODO: should this always be written? ( because it could contain metadata, which the user does not want to save!)
@@ -40,7 +39,6 @@ class VaultSettingsJsonAdapter {
String individualMountPath = null;
String winDriveLetter = null;
boolean unlockAfterStartup = VaultSettings.DEFAULT_UNLOCK_AFTER_STARTUP;
boolean mountAfterUnlock = VaultSettings.DEFAULT_MOUNT_AFTER_UNLOCK;
boolean revealAfterMount = VaultSettings.DEFAULT_REAVEAL_AFTER_MOUNT;
boolean usesIndividualMountPath = VaultSettings.DEFAULT_USES_INDIVIDUAL_MOUNTPATH;
@@ -63,9 +61,6 @@ class VaultSettingsJsonAdapter {
case "unlockAfterStartup":
unlockAfterStartup = in.nextBoolean();
break;
case "mountAfterUnlock":
mountAfterUnlock = in.nextBoolean();
break;
case "revealAfterMount":
revealAfterMount = in.nextBoolean();
break;
@@ -87,7 +82,6 @@ class VaultSettingsJsonAdapter {
vaultSettings.path().set(Paths.get(path));
vaultSettings.winDriveLetter().set(winDriveLetter);
vaultSettings.unlockAfterStartup().set(unlockAfterStartup);
vaultSettings.mountAfterUnlock().set(mountAfterUnlock);
vaultSettings.revealAfterMount().set(revealAfterMount);
vaultSettings.usesIndividualMountPath().set(usesIndividualMountPath);
vaultSettings.individualMountPath().set(individualMountPath);

View File

@@ -107,9 +107,6 @@ public class UnlockController implements ViewController {
@FXML
private CheckBox savePassword;
@FXML
private CheckBox mountAfterUnlock;
@FXML
private TextField mountName;
@@ -159,8 +156,6 @@ public class UnlockController implements ViewController {
public void initialize() {
advancedOptions.managedProperty().bind(advancedOptions.visibleProperty());
unlockButton.disableProperty().bind(passwordField.textProperty().isEmpty());
mountName.disableProperty().bind(mountAfterUnlock.selectedProperty().not());
revealAfterMount.disableProperty().bind(mountAfterUnlock.selectedProperty().not());
mountName.addEventFilter(KeyEvent.KEY_TYPED, this::filterAlphanumericKeyEvents);
mountName.textProperty().addListener(this::mountNameDidChange);
savePassword.setDisable(!keychainAccess.isPresent());
@@ -250,12 +245,10 @@ public class UnlockController implements ViewController {
}
VaultSettings vaultSettings = vault.getVaultSettings();
unlockAfterStartup.setSelected(savePassword.isSelected() && vaultSettings.unlockAfterStartup().get());
mountAfterUnlock.setSelected(vaultSettings.mountAfterUnlock().get());
revealAfterMount.setSelected(vaultSettings.revealAfterMount().get());
useOwnMountPath.setSelected(vaultSettings.usesIndividualMountPath().get());
vaultSubs = vaultSubs.and(EasyBind.subscribe(unlockAfterStartup.selectedProperty(), vaultSettings.unlockAfterStartup()::set));
vaultSubs = vaultSubs.and(EasyBind.subscribe(mountAfterUnlock.selectedProperty(), vaultSettings.mountAfterUnlock()::set));
vaultSubs = vaultSubs.and(EasyBind.subscribe(revealAfterMount.selectedProperty(), vaultSettings.revealAfterMount()::set));
vaultSubs = vaultSubs.and(EasyBind.subscribe(useOwnMountPath.selectedProperty(), vaultSettings.usesIndividualMountPath()::set));

View File

@@ -83,15 +83,6 @@ public class UnlockedController implements ViewController {
@FXML
private ContextMenu moreOptionsMenu;
@FXML
private MenuItem mountVaultMenuItem;
@FXML
private MenuItem unmountVaultMenuItem;
@FXML
private MenuItem revealVaultMenuItem;
@FXML
private VBox root;
@@ -103,10 +94,6 @@ public class UnlockedController implements ViewController {
@Override
public void initialize() {
mountVaultMenuItem.disableProperty().bind(vaultState.isEqualTo(Vault.State.UNLOCKED).not()); // enable when unlocked
unmountVaultMenuItem.disableProperty().bind(vaultState.isEqualTo(Vault.State.MOUNTED).not()); // enable when mounted
revealVaultMenuItem.disableProperty().bind(vaultState.isEqualTo(Vault.State.MOUNTED).not()); // enable when mounted
EasyBind.subscribe(vault, this::vaultChanged);
EasyBind.subscribe(moreOptionsMenu.showingProperty(), moreOptionsButton::setSelected);
}
@@ -121,10 +108,6 @@ public class UnlockedController implements ViewController {
return;
}
if (newVault.getState() == Vault.State.UNLOCKED && newVault.getVaultSettings().mountAfterUnlock().get()) {
mountVault(newVault);
}
// (re)start throughput statistics:
stopIoSampling();
startIoSampling();
@@ -132,57 +115,16 @@ public class UnlockedController implements ViewController {
@FXML
private void didClickLockVault(ActionEvent event) {
regularUnmountVault(this::lockVault);
regularLockVault(this::lockVaultSucceeded);
}
private void lockVault() {
try {
vault.get().lock();
} catch (ServerLifecycleException | IOException e) {
LOG.error("Lock failed", e);
}
private void lockVaultSucceeded() {
listener.ifPresent(listener -> listener.didLock(this));
}
@FXML
private void didClickMoreOptions(ActionEvent event) {
if (moreOptionsMenu.isShowing()) {
moreOptionsMenu.hide();
} else {
moreOptionsMenu.setAnchorLocation(AnchorLocation.CONTENT_TOP_RIGHT);
moreOptionsMenu.show(moreOptionsButton, Side.BOTTOM, moreOptionsButton.getWidth(), 0.0);
}
}
@FXML
public void didClickMountVault(ActionEvent event) {
mountVault(vault.get());
}
private void mountVault(Vault vault) {
private void regularLockVault(Runnable onSuccess) {
asyncTaskService.asyncTaskOf(() -> {
vault.mount();
}).onSuccess(() -> {
LOG.trace("Mount succeeded.");
messageLabel.setText(null);
if (vault.getVaultSettings().revealAfterMount().get()) {
revealVault(vault);
}
}).onError(CommandFailedException.class, e -> {
LOG.error("Mount failed.", e);
// TODO Markus Kreusch #393: hyperlink auf FAQ oder sowas?
messageLabel.setText(localization.getString("unlocked.label.mountFailed"));
}).run();
}
@FXML
public void didClickUnmountVault(ActionEvent event) {
regularUnmountVault(Runnables.doNothing());
}
private void regularUnmountVault(Runnable onSuccess) {
asyncTaskService.asyncTaskOf(() -> {
vault.get().unmount();
vault.get().lock(false);
}).onSuccess(() -> {
LOG.trace("Regular unmount succeeded.");
onSuccess.run();
@@ -191,18 +133,6 @@ public class UnlockedController implements ViewController {
}).run();
}
private void forcedUnmountVault(Runnable onSuccess) {
asyncTaskService.asyncTaskOf(() -> {
vault.get().unmountForced();
}).onSuccess(() -> {
LOG.trace("Forced unmount succeeded.");
onSuccess.run();
}).onError(Exception.class, e -> {
LOG.error("Forced unmount failed.", e);
messageLabel.setText(localization.getString("unlocked.label.unmountFailed"));
}).run();
}
private void onRegularUnmountVaultFailed(Exception e, Runnable onSuccess) {
if (vault.get().supportsForcedUnmount()) {
LOG.trace("Regular unmount failed.", e);
@@ -214,7 +144,7 @@ public class UnlockedController implements ViewController {
Optional<ButtonType> choice = confirmDialog.showAndWait();
if (ButtonType.YES.equals(choice.get())) {
forcedUnmountVault(onSuccess);
forcedLockVault(onSuccess);
} else {
LOG.trace("Unmount cancelled.", e);
}
@@ -224,6 +154,28 @@ public class UnlockedController implements ViewController {
}
}
private void forcedLockVault(Runnable onSuccess) {
asyncTaskService.asyncTaskOf(() -> {
vault.get().lock(true);
}).onSuccess(() -> {
LOG.trace("Forced unmount succeeded.");
onSuccess.run();
}).onError(Exception.class, e -> {
LOG.error("Forced unmount failed.", e);
messageLabel.setText(localization.getString("unlocked.label.unmountFailed"));
}).run();
}
@FXML
private void didClickMoreOptions(ActionEvent event) {
if (moreOptionsMenu.isShowing()) {
moreOptionsMenu.hide();
} else {
moreOptionsMenu.setAnchorLocation(AnchorLocation.CONTENT_TOP_RIGHT);
moreOptionsMenu.show(moreOptionsButton, Side.BOTTOM, moreOptionsButton.getWidth(), 0.0);
}
}
@FXML
private void didClickRevealVault(ActionEvent event) {
revealVault(vault.get());

View File

@@ -68,9 +68,7 @@ public class DirectoryListCell extends DraggableListCell<Vault> {
}
switch (state) {
case UNLOCKED:
case MOUNTED:
case MOUNTING:
case UNMOUNTING:
case PROCESSING:
return "\uf09c";
case LOCKED:
default:
@@ -84,9 +82,7 @@ public class DirectoryListCell extends DraggableListCell<Vault> {
}
switch (state) {
case UNLOCKED:
case MOUNTED:
case MOUNTING:
case UNMOUNTING:
case PROCESSING:
return UNLOCKED_ICON_COLOR;
case LOCKED:
default:

View File

@@ -73,26 +73,14 @@ public class AutoUnlocker {
}
try {
vault.unlock(CharBuffer.wrap(storedPw));
mountSilently(vault);
} catch (IOException | CryptoException e) {
revealSilently(vault);
} catch (IOException | CryptoException | CommandFailedException e) {
LOG.error("Auto unlock failed.", e);
} finally {
Arrays.fill(storedPw, ' ');
}
}
private void mountSilently(Vault unlockedVault) {
if (!unlockedVault.getVaultSettings().mountAfterUnlock().get()) {
return;
}
try {
unlockedVault.mount();
revealSilently(unlockedVault);
} catch (CommandFailedException e) {
LOG.error("Auto unlock succeded, but mounting the drive failed.", e);
}
}
private void revealSilently(Vault mountedVault) {
if (!mountedVault.getVaultSettings().revealAfterMount().get()) {
return;

View File

@@ -31,7 +31,6 @@ public class FuseVolume implements Volume {
private static final String DEFAULT_MOUNTROOTPATH_LINUX = System.getProperty("user.home") + "/.Cryptomator";
private final VaultSettings vaultSettings;
private final WindowsDriveLetters windowsDriveLetters;
private Mount fuseMnt;
private CryptoFileSystem cfs;
@@ -39,26 +38,16 @@ public class FuseVolume implements Volume {
private boolean extraDirCreated;
@Inject
public FuseVolume(VaultSettings vaultSettings, WindowsDriveLetters windowsDriveLetters) {
public FuseVolume(VaultSettings vaultSettings) {
this.vaultSettings = vaultSettings;
this.windowsDriveLetters = windowsDriveLetters;
this.extraDirCreated = false;
}
@Override
public void prepare(CryptoFileSystem fs) throws IOException, FuseNotSupportedException {
public void mount(CryptoFileSystem fs) throws IOException, FuseNotSupportedException, CommandFailedException {
this.cfs = fs;
String mountPath;
if (SystemUtils.IS_OS_WINDOWS) {
//windows case
if (vaultSettings.winDriveLetter().get() != null) {
// specific drive letter selected
mountPath = vaultSettings.winDriveLetter().get() + ":\\";
} else {
// auto assign drive letter
mountPath = windowsDriveLetters.getAvailableDriveLetters().iterator().next() + ":\\";
}
} else if (vaultSettings.usesIndividualMountPath().get()) {
if (vaultSettings.usesIndividualMountPath().get()) {
//specific path given
mountPath = vaultSettings.individualMountPath().get();
} else {
@@ -67,6 +56,7 @@ public class FuseVolume implements Volume {
extraDirCreated = true;
}
this.mountPath = Paths.get(mountPath).toAbsolutePath();
mount();
}
private String createDirIfNotExist(String prefix, String dirName) throws IOException {
@@ -87,8 +77,7 @@ public class FuseVolume implements Volume {
}
}
@Override
public void mount() throws CommandFailedException {
private void mount() throws CommandFailedException {
try {
EnvironmentVariables envVars = EnvironmentVariables.create()
.withMountName(vaultSettings.mountName().getValue())
@@ -117,15 +106,10 @@ public class FuseVolume implements Volume {
} catch (org.cryptomator.frontend.fuse.mount.CommandFailedException e) {
throw new CommandFailedException(e);
}
cleanup();
}
@Override
public synchronized void unmountForced() throws CommandFailedException {
unmount();
}
@Override
public void stop() {
private void cleanup() {
if (extraDirCreated) {
try {
Files.delete(mountPath);
@@ -135,19 +119,9 @@ public class FuseVolume implements Volume {
}
}
@Override
public String getMountUri() {
return "";
}
@Override
public boolean isSupported() {
return FuseMountFactory.isFuseSupported();
}
@Override
public boolean supportsForcedUnmount() {
return false;
return (SystemUtils.IS_OS_MAC_OSX || SystemUtils.IS_OS_LINUX) && FuseMountFactory.isFuseSupported();
}
}

View File

@@ -20,16 +20,6 @@ import java.util.function.Predicate;
import javax.inject.Inject;
import org.cryptomator.common.LazyInitializer;
import org.cryptomator.common.settings.Settings;
import org.cryptomator.common.settings.VaultSettings;
import org.cryptomator.cryptofs.CryptoFileSystem;
import org.cryptomator.cryptofs.CryptoFileSystemProperties;
import org.cryptomator.cryptofs.CryptoFileSystemProvider;
import org.cryptomator.cryptolib.api.CryptoException;
import org.cryptomator.cryptolib.api.InvalidPassphraseException;
import org.cryptomator.ui.model.VaultModule.PerVault;
import javafx.application.Platform;
import javafx.beans.Observable;
import javafx.beans.binding.Binding;
@@ -39,6 +29,15 @@ import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.StringProperty;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.SystemUtils;
import org.cryptomator.common.LazyInitializer;
import org.cryptomator.common.settings.Settings;
import org.cryptomator.common.settings.VaultSettings;
import org.cryptomator.cryptofs.CryptoFileSystem;
import org.cryptomator.cryptofs.CryptoFileSystemProperties;
import org.cryptomator.cryptofs.CryptoFileSystemProvider;
import org.cryptomator.cryptolib.api.CryptoException;
import org.cryptomator.cryptolib.api.InvalidPassphraseException;
import org.cryptomator.ui.model.VaultModule.PerVault;
import org.fxmisc.easybind.EasyBind;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -59,7 +58,7 @@ public class Vault {
private Volume volume;
public enum State {
LOCKED, UNLOCKED, MOUNTING, MOUNTED, UNMOUNTING
LOCKED, PROCESSING, UNLOCKED
}
@Inject
@@ -98,51 +97,33 @@ public class Vault {
CryptoFileSystemProvider.changePassphrase(getPath(), MASTERKEY_FILENAME, oldPassphrase, newPassphrase);
}
public synchronized void unlock(CharSequence passphrase) throws CryptoException, IOException {
public synchronized void unlock(CharSequence passphrase) throws CryptoException, IOException, CommandFailedException {
Platform.runLater(() -> {
state.set(State.PROCESSING);
});
CryptoFileSystem fs = getCryptoFileSystem(passphrase);
volume.prepare(fs);
volume.mount(fs);
Platform.runLater(() -> {
state.set(State.UNLOCKED);
});
}
public synchronized void mount() throws CommandFailedException {
public synchronized void lock(boolean forced) throws CommandFailedException {
Platform.runLater(() -> {
state.set(State.MOUNTING);
});
volume.mount();
Platform.runLater(() -> {
state.set(State.MOUNTED);
});
}
public synchronized void unmountForced() throws CommandFailedException {
unmount(true);
}
public synchronized void unmount() throws CommandFailedException {
unmount(false);
}
private synchronized void unmount(boolean forced) throws CommandFailedException {
Platform.runLater(() -> {
state.set(State.UNMOUNTING);
state.set(State.PROCESSING);
});
if (forced && volume.supportsForcedUnmount()) {
volume.unmountForced();
} else {
volume.unmount();
}
Platform.runLater(() -> {
state.set(State.UNLOCKED);
});
}
public synchronized void lock() throws IOException {
volume.stop();
CryptoFileSystem fs = cryptoFileSystem.getAndSet(null);
if (fs != null) {
fs.close();
try {
fs.close();
} catch (IOException e) {
LOG.error("Error closing file system.", e);
}
}
Platform.runLater(() -> {
state.set(State.LOCKED);
@@ -154,23 +135,18 @@ public class Vault {
*/
public void prepareForShutdown() {
try {
unmount();
lock(false);
} catch (CommandFailedException e) {
if (volume.supportsForcedUnmount()) {
try {
unmountForced();
lock(true);
} catch (CommandFailedException e1) {
LOG.warn("Failed to force unmount vault.");
LOG.warn("Failed to force lock vault.", e1);
}
} else {
LOG.warn("Failed to gracefully unmount vault.");
LOG.warn("Failed to gracefully lock vault.", e);
}
}
try {
lock();
} catch (Exception e) {
LOG.warn("Failed to lock vault.");
}
}
public void reveal() throws CommandFailedException {
@@ -289,10 +265,6 @@ public class Vault {
}
}
public String getFilesystemRootUrl() {
return volume.getMountUri();
}
public String getId() {
return vaultSettings.getId();
}

View File

@@ -9,9 +9,18 @@ import java.io.IOException;
*/
public interface Volume {
void prepare(CryptoFileSystem fs) throws IOException;
/**
* Checks in constant time whether this volume type is supported on the system running Cryptomator.
* @return true if this volume can be mounted
*/
boolean isSupported();
void mount() throws CommandFailedException;
/**
*
* @param fs
* @throws IOException
*/
void mount(CryptoFileSystem fs) throws IOException, CommandFailedException;
default void reveal() throws CommandFailedException {
throw new CommandFailedException("Not implemented.");
@@ -19,20 +28,14 @@ public interface Volume {
void unmount() throws CommandFailedException;
default void unmountForced() throws CommandFailedException {
throw new CommandFailedException("Operation not supported.");
}
void stop();
String getMountUri();
default boolean isSupported() {
return false;
}
// optional forced unmounting:
default boolean supportsForcedUnmount() {
return false;
}
default void unmountForced() throws CommandFailedException {
throw new CommandFailedException("Operation not supported.");
}
}

View File

@@ -36,7 +36,7 @@ public class WebDavVolume implements Volume {
}
@Override
public void prepare(CryptoFileSystem fs) {
public void mount(CryptoFileSystem fs) throws CommandFailedException {
if (server == null) {
server = serverProvider.get();
}
@@ -45,10 +45,10 @@ public class WebDavVolume implements Volume {
}
servlet = server.createWebDavServlet(fs.getPath("/"), vaultSettings.getId() + "/" + vaultSettings.mountName().get());
servlet.start();
mount();
}
@Override
public void mount() throws CommandFailedException {
private void mount() throws CommandFailedException {
if (servlet == null) {
throw new IllegalStateException("Mounting requires unlocked WebDAV servlet.");
}
@@ -82,11 +82,17 @@ public class WebDavVolume implements Volume {
} catch (Mounter.CommandFailedException e) {
throw new CommandFailedException(e);
}
cleanup();
}
@Override
public synchronized void unmountForced() {
mount.forced();
public synchronized void unmountForced() throws CommandFailedException {
try {
mount.forced().orElseThrow(IllegalStateException::new).unmount();
} catch (Mounter.CommandFailedException e) {
throw new CommandFailedException(e);
}
cleanup();
}
private String getLocalhostAliasOrNull() {
@@ -102,28 +108,19 @@ public class WebDavVolume implements Volume {
}
}
@Override
public void stop() {
private void cleanup() {
if (servlet != null) {
servlet.stop();
}
}
public synchronized String getMountUri() {
return servlet.getServletRootUri().toString() + "/";
}
/**
* TODO: what to check wether it is implemented?
*
* @return
*/
@Override
public boolean isSupported() {
return true;
}
@Override
public boolean supportsForcedUnmount() {
return mount != null && mount.forced().isPresent();
}

View File

@@ -75,28 +75,25 @@
<!-- Row 3.2 -->
<CheckBox GridPane.rowIndex="2" GridPane.columnIndex="0" GridPane.columnSpan="2" fx:id="unlockAfterStartup" text="%unlock.label.unlockAfterStartup" cacheShape="true" cache="true" />
<!-- Row 3.3 -->
<CheckBox GridPane.rowIndex="3" GridPane.columnIndex="0" GridPane.columnSpan="2" fx:id="mountAfterUnlock" text="%unlock.label.mountAfterUnlock" cacheShape="true" cache="true" />
<Label GridPane.rowIndex="3" GridPane.columnIndex="0" text="%unlock.label.mountName" cacheShape="true" cache="true" />
<TextField GridPane.rowIndex="3" GridPane.columnIndex="1" fx:id="mountName" GridPane.hgrow="ALWAYS" maxWidth="Infinity" cacheShape="true" cache="true" />
<!-- Row 3.4 -->
<Label GridPane.rowIndex="4" GridPane.columnIndex="0" text="%unlock.label.mountName" cacheShape="true" cache="true" />
<TextField GridPane.rowIndex="4" GridPane.columnIndex="1" fx:id="mountName" GridPane.hgrow="ALWAYS" maxWidth="Infinity" cacheShape="true" cache="true" />
<CheckBox GridPane.rowIndex="4" GridPane.columnIndex="0" GridPane.columnSpan="2" fx:id="revealAfterMount" text="%unlock.label.revealAfterMount" cacheShape="true" cache="true" />
<!-- Row 3.5 -->
<CheckBox GridPane.rowIndex="5" GridPane.columnIndex="0" GridPane.columnSpan="2" fx:id="revealAfterMount" text="%unlock.label.revealAfterMount" cacheShape="true" cache="true" />
<!-- Row 3.6 Alt1 -->
<Label GridPane.rowIndex="6" GridPane.columnIndex="0" fx:id="winDriveLetterLabel" text="%unlock.label.winDriveLetter" cacheShape="true" cache="true" />
<ChoiceBox GridPane.rowIndex="6" GridPane.columnIndex="1" fx:id="winDriveLetter" GridPane.hgrow="ALWAYS" maxWidth="Infinity" cacheShape="true" cache="true" />
<!-- Row 3.5 Alt1 -->
<Label GridPane.rowIndex="5" GridPane.columnIndex="0" fx:id="winDriveLetterLabel" text="%unlock.label.winDriveLetter" cacheShape="true" cache="true" />
<ChoiceBox GridPane.rowIndex="5" GridPane.columnIndex="1" fx:id="winDriveLetter" GridPane.hgrow="ALWAYS" maxWidth="Infinity" cacheShape="true" cache="true" />
<!-- Row 3.6 Alt2 -->
<CheckBox GridPane.rowIndex="6" GridPane.columnIndex="0" fx:id="useOwnMountPath" text="%unlock.label.useOwnMountPath" cacheShape="true" cache="true" />
<!-- Row 3.5 Alt2 -->
<CheckBox GridPane.rowIndex="5" GridPane.columnIndex="0" fx:id="useOwnMountPath" text="%unlock.label.useOwnMountPath" cacheShape="true" cache="true" />
<Label GridPane.rowIndex="7" GridPane.columnIndex="0" fx:id="mountPathLabel" text="%unlock.label.mountPath" cacheShape="true" cache="true" />
<Label GridPane.rowIndex="6" GridPane.columnIndex="0" fx:id="mountPathLabel" text="%unlock.label.mountPath" cacheShape="true" cache="true" />
<HBox GridPane.rowIndex="7" GridPane.columnIndex="1" fx:id="mountPathBox" spacing="6.0">
<TextField GridPane.rowIndex="7" GridPane.columnIndex="1" fx:id="mountPath" cacheShape="true" cache="true" />
<HBox GridPane.rowIndex="6" GridPane.columnIndex="1" fx:id="mountPathBox" spacing="6.0">
<TextField fx:id="mountPath" cacheShape="true" cache="true" />
<Button text="%unlock.label.mountPathButton" fx:id="changeMountPathButton" onAction="#didClickchangeMountPathButton"/>
</HBox>

View File

@@ -28,12 +28,6 @@
<fx:define>
<ContextMenu fx:id="moreOptionsMenu">
<items>
<MenuItem fx:id="mountVaultMenuItem" text="%unlocked.moreOptions.mount" onAction="#didClickMountVault">
<graphic><Label text="&#xf139;" styleClass="ionicons"/></graphic>
</MenuItem>
<MenuItem fx:id="unmountVaultMenuItem" text="%unlocked.moreOptions.unmount" onAction="#didClickUnmountVault">
<graphic><Label text="&#xf131;" styleClass="ionicons"/></graphic>
</MenuItem>
<MenuItem fx:id="revealVaultMenuItem" text="%unlocked.moreOptions.reveal" onAction="#didClickRevealVault">
<graphic><Label text="&#xf133;" styleClass="ionicons"/></graphic>
</MenuItem>

View File

@@ -62,7 +62,6 @@ upgrade.version5toX.msg=This vault needs to be migrated to a newer format.\nPlea
# unlock.fxml
unlock.label.password=Password
unlock.label.savePassword=Save Password
unlock.label.mountAfterUnlock=Mount Drive
unlock.label.mountName=Drive Name
unlock.label.unlockAfterStartup=Auto-Unlock on Start (Experimental)
unlock.label.revealAfterMount=Reveal Drive
@@ -100,8 +99,6 @@ changePassword.errorMessage.decryptionFailed=Decryption failed
# unlocked.fxml
unlocked.button.lock=Lock Vault
unlocked.moreOptions.mount=Mount Drive
unlocked.moreOptions.unmount=Eject Drive
unlocked.moreOptions.reveal=Reveal Drive
unlocked.label.mountFailed=Connecting drive failed
unlocked.label.revealFailed=Command failed