diff --git a/main/ui/src/main/java/org/cryptomator/ui/controllers/UnlockedController.java b/main/ui/src/main/java/org/cryptomator/ui/controllers/UnlockedController.java index 3d0e58aa4..ae11098d2 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/controllers/UnlockedController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/controllers/UnlockedController.java @@ -38,6 +38,7 @@ import javafx.scene.chart.XYChart.Data; import javafx.scene.chart.XYChart.Series; import javafx.scene.control.ContextMenu; import javafx.scene.control.Label; +import javafx.scene.control.MenuItem; import javafx.scene.control.ToggleButton; import javafx.scene.input.Clipboard; import javafx.scene.input.ClipboardContent; @@ -81,11 +82,16 @@ public class UnlockedController extends LocalizedFXMLViewController { @FXML private ContextMenu moreOptionsMenu; + @FXML + private MenuItem revealVaultMenuItem; + @Override public void initialize() { macWarningsController.initStage(macWarningsWindow); ActiveWindowStyleSupport.startObservingFocus(macWarningsWindow); + revealVaultMenuItem.disableProperty().bind(EasyBind.map(vault, vault -> vault != null && !vault.isMounted())); + EasyBind.subscribe(vault, this::vaultChanged); EasyBind.subscribe(moreOptionsMenu.showingProperty(), moreOptionsButton::setSelected); } @@ -109,6 +115,11 @@ public class UnlockedController extends LocalizedFXMLViewController { } }); + if (!vault.get().isMounted()) { + // TODO Markus Kreusch #393: hyperlink auf FAQ oder sowas? + messageLabel.setText(localization.getString("unlocked.label.mountFailed")); + } + // (re)start throughput statistics: stopIoSampling(); startIoSampling(); diff --git a/main/ui/src/main/java/org/cryptomator/ui/model/Vault.java b/main/ui/src/main/java/org/cryptomator/ui/model/Vault.java index 086fffa90..0d36158fc 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/model/Vault.java +++ b/main/ui/src/main/java/org/cryptomator/ui/model/Vault.java @@ -50,6 +50,8 @@ import org.cryptomator.ui.util.DeferredClosable; import org.cryptomator.ui.util.DeferredCloser; import org.cryptomator.ui.util.FXThreads; import org.fxmisc.easybind.EasyBind; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.google.common.collect.ImmutableMap; @@ -65,6 +67,8 @@ import javafx.collections.ObservableList; public class Vault implements CryptoFileSystemDelegate { + private static final Logger LOG = LoggerFactory.getLogger(CryptoFileSystemDelegate.class); + public static final String VAULT_FILE_EXTENSION = ".cryptomator"; private final ObjectProperty path; @@ -72,6 +76,7 @@ public class Vault implements CryptoFileSystemDelegate { private final CryptoFileSystemFactory cryptoFileSystemFactory; private final DeferredCloser closer; private final BooleanProperty unlocked = new SimpleBooleanProperty(); + private final BooleanProperty mounted = new SimpleBooleanProperty(); private final ObservableList namesOfResourcesWithInvalidMac = FXThreads.observableListOnMainThread(FXCollections.observableArrayList()); private final Set whitelistedResourcesWithInvalidMac = new HashSet<>(); private final AtomicReference nioFileSystem = new AtomicReference<>(); @@ -131,7 +136,8 @@ public class Vault implements CryptoFileSystemDelegate { } public synchronized void activateFrontend(FrontendFactory frontendFactory, Settings settings, CharSequence passphrase) throws FrontendCreationFailedException { - boolean success = false; + boolean launchSuccess = false; + boolean mountSuccess = false; try { FileSystem fs = getNioFileSystem(); FileSystem shorteningFs = shorteningFileSystemFactory.get(fs); @@ -140,22 +146,32 @@ public class Vault implements CryptoFileSystemDelegate { StatsFileSystem statsFs = new StatsFileSystem(normalizingFs); statsFileSystem = Optional.of(statsFs); Frontend frontend = frontendFactory.create(statsFs, FrontendId.from(id), stripStart(mountName, "/")); + launchSuccess = true; filesystemFrontend = closer.closeLater(frontend); frontend.mount(getMountParams(settings)); - success = true; - } catch (UncheckedIOException | CommandFailedException e) { + mountSuccess = true; + } catch (UncheckedIOException e) { throw new FrontendCreationFailedException(e); + } catch (CommandFailedException e) { + LOG.error("Failed to mount vault " + mountName, e); } finally { // unlocked is a observable property and should only be changed by the FX application thread - final boolean finalSuccess = success; - Platform.runLater(() -> unlocked.set(finalSuccess)); + boolean finalLaunchSuccess = launchSuccess; + boolean finalMountSuccess = mountSuccess; + Platform.runLater(() -> { + unlocked.set(finalLaunchSuccess); + mounted.set(finalMountSuccess); + }); } } public synchronized void deactivateFrontend() throws Exception { filesystemFrontend.close(); statsFileSystem = Optional.empty(); - Platform.runLater(() -> unlocked.set(false)); + Platform.runLater(() -> { + mounted.set(false); + unlocked.set(false); + }); } private Map> getMountParams(Settings settings) { @@ -239,10 +255,18 @@ public class Vault implements CryptoFileSystemDelegate { return unlocked; } + public BooleanProperty mountedProperty() { + return mounted; + } + public boolean isUnlocked() { return unlocked.get(); } + public boolean isMounted() { + return mounted.get(); + } + public ObservableList getNamesOfResourcesWithInvalidMac() { return namesOfResourcesWithInvalidMac; } diff --git a/main/ui/src/main/resources/fxml/unlocked.fxml b/main/ui/src/main/resources/fxml/unlocked.fxml index 05ead1532..81dfddd5f 100644 --- a/main/ui/src/main/resources/fxml/unlocked.fxml +++ b/main/ui/src/main/resources/fxml/unlocked.fxml @@ -28,7 +28,7 @@ - + diff --git a/main/ui/src/main/resources/localization/de.txt b/main/ui/src/main/resources/localization/de.txt index 7761861c9..2b301d0ae 100644 --- a/main/ui/src/main/resources/localization/de.txt +++ b/main/ui/src/main/resources/localization/de.txt @@ -48,6 +48,7 @@ changePassword.infoMessage.success = Passwort geändert unlocked.button.lock = Tresor sperren unlocked.moreOptions.reveal = Laufwerk anzeigen unlocked.moreOptions.copyUrl = WebDAV-URL kopieren +unlocked.label.mountFailed = Verbinden des Laufwerks fehlgeschlagen unlocked.label.revealFailed = Befehl fehlgeschlagen unlocked.label.unmountFailed = Trennen des Laufwerks fehlgeschlagen unlocked.label.statsEncrypted = verschlüsselt diff --git a/main/ui/src/main/resources/localization/en.txt b/main/ui/src/main/resources/localization/en.txt index 92cd4815a..63f8551b0 100644 --- a/main/ui/src/main/resources/localization/en.txt +++ b/main/ui/src/main/resources/localization/en.txt @@ -79,6 +79,7 @@ changePassword.errorMessage.decryptionFailed=Decryption failed unlocked.button.lock=Lock vault unlocked.moreOptions.reveal=Reveal drive unlocked.moreOptions.copyUrl=Copy WebDAV URL +unlocked.label.mountFailed=Connecting drive failed unlocked.label.revealFailed=Command failed unlocked.label.unmountFailed=Ejecting drive failed unlocked.label.statsEncrypted=encrypted