diff --git a/.idea/compiler.xml b/.idea/compiler.xml index 18e7c76e0..e9c70c10f 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -45,7 +45,7 @@ \ No newline at end of file diff --git a/pom.xml b/pom.xml index e1e15fd54..ca7e9ee82 100644 --- a/pom.xml +++ b/pom.xml @@ -313,6 +313,7 @@ -Adagger.fastInit=enabled -Adagger.formatGeneratedSource=enabled + --enable-preview diff --git a/src/main/java/org/cryptomator/common/vaults/Vault.java b/src/main/java/org/cryptomator/common/vaults/Vault.java index ea54ed9d5..95e08eaa0 100644 --- a/src/main/java/org/cryptomator/common/vaults/Vault.java +++ b/src/main/java/org/cryptomator/common/vaults/Vault.java @@ -37,6 +37,7 @@ import javax.inject.Named; import javafx.beans.Observable; import javafx.beans.binding.Bindings; import javafx.beans.binding.BooleanBinding; +import javafx.beans.binding.ObjectBinding; import javafx.beans.binding.StringBinding; import javafx.beans.property.BooleanProperty; import javafx.beans.property.ObjectProperty; @@ -81,7 +82,7 @@ public class Vault { private final BooleanBinding missing; private final BooleanBinding needsMigration; private final BooleanBinding unknownError; - private final StringBinding accessPoint; + private final ObjectBinding mountPoint; private final BooleanProperty showingStats; private AtomicReference mountHandle = new AtomicReference<>(null); @@ -105,7 +106,7 @@ public class Vault { this.missing = Bindings.createBooleanBinding(this::isMissing, state); this.needsMigration = Bindings.createBooleanBinding(this::isNeedsMigration, state); this.unknownError = Bindings.createBooleanBinding(this::isUnknownError, state); - this.accessPoint = Bindings.createStringBinding(this::getAccessPoint, state); + this.mountPoint = Bindings.createObjectBinding(this::getMountPoint, state); this.showingStats = new SimpleBooleanProperty(false); } @@ -317,17 +318,13 @@ public class Vault { return vaultSettings.displayName().get(); } - public StringBinding accessPointProperty() { - return accessPoint; + public ObjectBinding mountPointProperty() { + return mountPoint; } - public String getAccessPoint() { - var mountPoint = mountHandle.get().mount.getMountpoint(); - if (mountPoint instanceof Mountpoint.WithPath m) { - return m.path().toString(); - } else { - return mountPoint.uri().toString(); - } + public Mountpoint getMountPoint() { + var handle = mountHandle.get(); + return handle == null ? null : handle.mount.getMountpoint(); } public StringBinding displayablePathProperty() { diff --git a/src/main/java/org/cryptomator/ui/common/HostServiceRevealer.java b/src/main/java/org/cryptomator/ui/common/HostServiceRevealer.java deleted file mode 100644 index 241347c01..000000000 --- a/src/main/java/org/cryptomator/ui/common/HostServiceRevealer.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.cryptomator.ui.common; - -import dagger.Lazy; -import org.cryptomator.ui.fxapp.FxApplicationScoped; - -import javax.inject.Inject; -import javafx.application.Application; -import java.nio.file.Path; - -@FxApplicationScoped -public class HostServiceRevealer { - - private final Lazy application; - - @Inject - public HostServiceRevealer(Lazy application) { - this.application = application; - } - - public void reveal(Path p) { - application.get().getHostServices().showDocument(p.toUri().toString()); - } -} diff --git a/src/main/java/org/cryptomator/ui/common/VaultService.java b/src/main/java/org/cryptomator/ui/common/VaultService.java index e8c7ca7c5..95129f6ee 100644 --- a/src/main/java/org/cryptomator/ui/common/VaultService.java +++ b/src/main/java/org/cryptomator/ui/common/VaultService.java @@ -1,13 +1,17 @@ package org.cryptomator.ui.common; +import dagger.Lazy; import org.cryptomator.common.vaults.Vault; import org.cryptomator.common.vaults.VaultState; +import org.cryptomator.integrations.mount.Mountpoint; import org.cryptomator.integrations.mount.UnmountFailedException; import org.cryptomator.ui.fxapp.FxApplicationScoped; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.inject.Inject; +import javafx.application.Application; +import javafx.application.HostServices; import javafx.concurrent.Task; import javafx.stage.Stage; import java.io.IOException; @@ -24,13 +28,13 @@ public class VaultService { private static final Logger LOG = LoggerFactory.getLogger(VaultService.class); + private final Lazy application; private final ExecutorService executorService; - private final HostServiceRevealer vaultRevealer; @Inject - public VaultService(ExecutorService executorService, HostServiceRevealer vaultRevealer) { + public VaultService(Lazy application, ExecutorService executorService) { + this.application = application; this.executorService = executorService; - this.vaultRevealer = vaultRevealer; } public void reveal(Vault vault) { @@ -43,7 +47,7 @@ public class VaultService { * @param vault The vault to reveal */ public Task createRevealTask(Vault vault) { - Task task = new RevealVaultTask(vault); + Task task = new RevealVaultTask(vault, application.get().getHostServices()); task.setOnSucceeded(evt -> LOG.info("Revealed {}", vault.getDisplayName())); task.setOnFailed(evt -> LOG.error("Failed to reveal " + vault.getDisplayName(), evt.getSource().getException())); return task; @@ -106,20 +110,21 @@ public class VaultService { private static class RevealVaultTask extends Task { private final Vault vault; + private final HostServices hostServices; - /** - * @param vault The vault to lock - */ - public RevealVaultTask(Vault vault) { + public RevealVaultTask(Vault vault, HostServices hostServices) { this.vault = vault; - + this.hostServices = hostServices; setOnFailed(evt -> LOG.error("Failed to reveal " + vault.getDisplayName(), getException())); } @Override protected Vault call() { - //vault.reveal(revealer); //TODO: just call hostApplication service - //application.get().getHostServices().showDocument(p.toUri().toString()); + switch (vault.getMountPoint()) { + case null -> LOG.warn("Not currently mounted"); + case Mountpoint.WithPath m -> hostServices.showDocument(m.uri().toString()); + case Mountpoint.WithUri m -> LOG.info("Vault mounted at {}", m.uri()); // TODO show in UI? + } return vault; } } diff --git a/src/main/java/org/cryptomator/ui/mainwindow/VaultDetailUnlockedController.java b/src/main/java/org/cryptomator/ui/mainwindow/VaultDetailUnlockedController.java index 63d88a6a4..c86ea1929 100644 --- a/src/main/java/org/cryptomator/ui/mainwindow/VaultDetailUnlockedController.java +++ b/src/main/java/org/cryptomator/ui/mainwindow/VaultDetailUnlockedController.java @@ -4,16 +4,24 @@ import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import org.cryptomator.common.vaults.Vault; +import org.cryptomator.common.vaults.VaultState; +import org.cryptomator.integrations.mount.Mountpoint; import org.cryptomator.ui.common.FxController; import org.cryptomator.ui.common.VaultService; import org.cryptomator.ui.fxapp.FxApplicationWindows; import org.cryptomator.ui.stats.VaultStatisticsComponent; import javax.inject.Inject; +import javafx.beans.binding.Bindings; +import javafx.beans.binding.BooleanBinding; +import javafx.beans.binding.StringBinding; import javafx.beans.property.ObjectProperty; import javafx.beans.property.ReadOnlyObjectProperty; +import javafx.beans.value.ObservableValue; import javafx.fxml.FXML; import javafx.stage.Stage; +import java.net.URI; +import java.util.Optional; @MainWindowScoped public class VaultDetailUnlockedController implements FxController { @@ -24,6 +32,10 @@ public class VaultDetailUnlockedController implements FxController { private final Stage mainWindow; private final LoadingCache vaultStats; private final VaultStatisticsComponent.Builder vaultStatsBuilder; + private final ObservableValue mountPoint; + private final ObservableValue accessibleViaPath; + private final ObservableValue accessibleViaUri; + private final ObservableValue mountUri; @Inject public VaultDetailUnlockedController(ObjectProperty vault, FxApplicationWindows appWindows, VaultService vaultService, VaultStatisticsComponent.Builder vaultStatsBuilder, @MainWindow Stage mainWindow) { @@ -33,6 +45,10 @@ public class VaultDetailUnlockedController implements FxController { this.mainWindow = mainWindow; this.vaultStats = CacheBuilder.newBuilder().weakValues().build(CacheLoader.from(this::buildVaultStats)); this.vaultStatsBuilder = vaultStatsBuilder; + this.mountPoint = vault.flatMap(Vault::mountPointProperty); + this.accessibleViaPath = mountPoint.map(m -> m instanceof Mountpoint.WithPath).orElse(false); + this.accessibleViaUri = mountPoint.map(m -> m instanceof Mountpoint.WithUri).orElse(false); + this.mountUri = mountPoint.map(Mountpoint::uri).map(URI::toASCIIString).orElse(""); } private VaultStatisticsComponent buildVaultStats(Vault vault) { @@ -44,6 +60,11 @@ public class VaultDetailUnlockedController implements FxController { vaultService.reveal(vault.get()); } + @FXML + public void copyMountUri() { + // TODO + } + @FXML public void lock() { appWindows.startLockWorkflow(vault.get(), mainWindow); @@ -64,4 +85,29 @@ public class VaultDetailUnlockedController implements FxController { return vault.get(); } + public ObservableValue accessibleViaPathProperty() { + return accessibleViaPath; + } + + public boolean isAccessibleViaPath() { + return accessibleViaPath.getValue(); + } + + public ObservableValue accessibleViaUriProperty() { + return accessibleViaUri; + } + + public boolean isAccessibleViaUri() { + return accessibleViaUri.getValue(); + } + + public ObservableValue mountUriProperty() { + return mountUri; + } + + public String getMountUri() { + return mountUri.getValue(); + } + + } diff --git a/src/main/resources/fxml/vault_detail_unlocked.fxml b/src/main/resources/fxml/vault_detail_unlocked.fxml index 4b4c66dd6..22cdc258b 100644 --- a/src/main/resources/fxml/vault_detail_unlocked.fxml +++ b/src/main/resources/fxml/vault_detail_unlocked.fxml @@ -12,21 +12,26 @@ alignment="TOP_CENTER" spacing="9">