reveal OR copy mount point depending on chosen mounter

This commit is contained in:
Sebastian Stenzel
2022-11-10 14:11:06 +01:00
parent 6dac00625c
commit 4029f86a0d
7 changed files with 84 additions and 53 deletions

2
.idea/compiler.xml generated
View File

@@ -45,7 +45,7 @@
</component> </component>
<component name="JavacSettings"> <component name="JavacSettings">
<option name="ADDITIONAL_OPTIONS_OVERRIDE"> <option name="ADDITIONAL_OPTIONS_OVERRIDE">
<module name="cryptomator" options="-Adagger.fastInit=enabled -Adagger.formatGeneratedSource=enabled" /> <module name="cryptomator" options="-Adagger.fastInit=enabled -Adagger.formatGeneratedSource=enabled --enable-preview" />
</option> </option>
</component> </component>
</project> </project>

View File

@@ -313,6 +313,7 @@
<compilerArgs> <compilerArgs>
<arg>-Adagger.fastInit=enabled</arg> <arg>-Adagger.fastInit=enabled</arg>
<arg>-Adagger.formatGeneratedSource=enabled</arg> <arg>-Adagger.formatGeneratedSource=enabled</arg>
<arg>--enable-preview</arg>
</compilerArgs> </compilerArgs>
</configuration> </configuration>
</plugin> </plugin>

View File

@@ -37,6 +37,7 @@ import javax.inject.Named;
import javafx.beans.Observable; import javafx.beans.Observable;
import javafx.beans.binding.Bindings; import javafx.beans.binding.Bindings;
import javafx.beans.binding.BooleanBinding; import javafx.beans.binding.BooleanBinding;
import javafx.beans.binding.ObjectBinding;
import javafx.beans.binding.StringBinding; import javafx.beans.binding.StringBinding;
import javafx.beans.property.BooleanProperty; import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty; import javafx.beans.property.ObjectProperty;
@@ -81,7 +82,7 @@ public class Vault {
private final BooleanBinding missing; private final BooleanBinding missing;
private final BooleanBinding needsMigration; private final BooleanBinding needsMigration;
private final BooleanBinding unknownError; private final BooleanBinding unknownError;
private final StringBinding accessPoint; private final ObjectBinding<Mountpoint> mountPoint;
private final BooleanProperty showingStats; private final BooleanProperty showingStats;
private AtomicReference<MountHandle> mountHandle = new AtomicReference<>(null); private AtomicReference<MountHandle> mountHandle = new AtomicReference<>(null);
@@ -105,7 +106,7 @@ public class Vault {
this.missing = Bindings.createBooleanBinding(this::isMissing, state); this.missing = Bindings.createBooleanBinding(this::isMissing, state);
this.needsMigration = Bindings.createBooleanBinding(this::isNeedsMigration, state); this.needsMigration = Bindings.createBooleanBinding(this::isNeedsMigration, state);
this.unknownError = Bindings.createBooleanBinding(this::isUnknownError, 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); this.showingStats = new SimpleBooleanProperty(false);
} }
@@ -317,17 +318,13 @@ public class Vault {
return vaultSettings.displayName().get(); return vaultSettings.displayName().get();
} }
public StringBinding accessPointProperty() { public ObjectBinding<Mountpoint> mountPointProperty() {
return accessPoint; return mountPoint;
} }
public String getAccessPoint() { public Mountpoint getMountPoint() {
var mountPoint = mountHandle.get().mount.getMountpoint(); var handle = mountHandle.get();
if (mountPoint instanceof Mountpoint.WithPath m) { return handle == null ? null : handle.mount.getMountpoint();
return m.path().toString();
} else {
return mountPoint.uri().toString();
}
} }
public StringBinding displayablePathProperty() { public StringBinding displayablePathProperty() {

View File

@@ -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> application;
@Inject
public HostServiceRevealer(Lazy<Application> application) {
this.application = application;
}
public void reveal(Path p) {
application.get().getHostServices().showDocument(p.toUri().toString());
}
}

View File

@@ -1,13 +1,17 @@
package org.cryptomator.ui.common; package org.cryptomator.ui.common;
import dagger.Lazy;
import org.cryptomator.common.vaults.Vault; import org.cryptomator.common.vaults.Vault;
import org.cryptomator.common.vaults.VaultState; import org.cryptomator.common.vaults.VaultState;
import org.cryptomator.integrations.mount.Mountpoint;
import org.cryptomator.integrations.mount.UnmountFailedException; import org.cryptomator.integrations.mount.UnmountFailedException;
import org.cryptomator.ui.fxapp.FxApplicationScoped; import org.cryptomator.ui.fxapp.FxApplicationScoped;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import javax.inject.Inject; import javax.inject.Inject;
import javafx.application.Application;
import javafx.application.HostServices;
import javafx.concurrent.Task; import javafx.concurrent.Task;
import javafx.stage.Stage; import javafx.stage.Stage;
import java.io.IOException; import java.io.IOException;
@@ -24,13 +28,13 @@ public class VaultService {
private static final Logger LOG = LoggerFactory.getLogger(VaultService.class); private static final Logger LOG = LoggerFactory.getLogger(VaultService.class);
private final Lazy<Application> application;
private final ExecutorService executorService; private final ExecutorService executorService;
private final HostServiceRevealer vaultRevealer;
@Inject @Inject
public VaultService(ExecutorService executorService, HostServiceRevealer vaultRevealer) { public VaultService(Lazy<Application> application, ExecutorService executorService) {
this.application = application;
this.executorService = executorService; this.executorService = executorService;
this.vaultRevealer = vaultRevealer;
} }
public void reveal(Vault vault) { public void reveal(Vault vault) {
@@ -43,7 +47,7 @@ public class VaultService {
* @param vault The vault to reveal * @param vault The vault to reveal
*/ */
public Task<Vault> createRevealTask(Vault vault) { public Task<Vault> createRevealTask(Vault vault) {
Task<Vault> task = new RevealVaultTask(vault); Task<Vault> task = new RevealVaultTask(vault, application.get().getHostServices());
task.setOnSucceeded(evt -> LOG.info("Revealed {}", vault.getDisplayName())); task.setOnSucceeded(evt -> LOG.info("Revealed {}", vault.getDisplayName()));
task.setOnFailed(evt -> LOG.error("Failed to reveal " + vault.getDisplayName(), evt.getSource().getException())); task.setOnFailed(evt -> LOG.error("Failed to reveal " + vault.getDisplayName(), evt.getSource().getException()));
return task; return task;
@@ -106,20 +110,21 @@ public class VaultService {
private static class RevealVaultTask extends Task<Vault> { private static class RevealVaultTask extends Task<Vault> {
private final Vault vault; private final Vault vault;
private final HostServices hostServices;
/** public RevealVaultTask(Vault vault, HostServices hostServices) {
* @param vault The vault to lock
*/
public RevealVaultTask(Vault vault) {
this.vault = vault; this.vault = vault;
this.hostServices = hostServices;
setOnFailed(evt -> LOG.error("Failed to reveal " + vault.getDisplayName(), getException())); setOnFailed(evt -> LOG.error("Failed to reveal " + vault.getDisplayName(), getException()));
} }
@Override @Override
protected Vault call() { protected Vault call() {
//vault.reveal(revealer); //TODO: just call hostApplication service switch (vault.getMountPoint()) {
//application.get().getHostServices().showDocument(p.toUri().toString()); 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; return vault;
} }
} }

View File

@@ -4,16 +4,24 @@ import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader; import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache; import com.google.common.cache.LoadingCache;
import org.cryptomator.common.vaults.Vault; 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.FxController;
import org.cryptomator.ui.common.VaultService; import org.cryptomator.ui.common.VaultService;
import org.cryptomator.ui.fxapp.FxApplicationWindows; import org.cryptomator.ui.fxapp.FxApplicationWindows;
import org.cryptomator.ui.stats.VaultStatisticsComponent; import org.cryptomator.ui.stats.VaultStatisticsComponent;
import javax.inject.Inject; 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.ObjectProperty;
import javafx.beans.property.ReadOnlyObjectProperty; import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.beans.value.ObservableValue;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.stage.Stage; import javafx.stage.Stage;
import java.net.URI;
import java.util.Optional;
@MainWindowScoped @MainWindowScoped
public class VaultDetailUnlockedController implements FxController { public class VaultDetailUnlockedController implements FxController {
@@ -24,6 +32,10 @@ public class VaultDetailUnlockedController implements FxController {
private final Stage mainWindow; private final Stage mainWindow;
private final LoadingCache<Vault, VaultStatisticsComponent> vaultStats; private final LoadingCache<Vault, VaultStatisticsComponent> vaultStats;
private final VaultStatisticsComponent.Builder vaultStatsBuilder; private final VaultStatisticsComponent.Builder vaultStatsBuilder;
private final ObservableValue<Mountpoint> mountPoint;
private final ObservableValue<Boolean> accessibleViaPath;
private final ObservableValue<Boolean> accessibleViaUri;
private final ObservableValue<String> mountUri;
@Inject @Inject
public VaultDetailUnlockedController(ObjectProperty<Vault> vault, FxApplicationWindows appWindows, VaultService vaultService, VaultStatisticsComponent.Builder vaultStatsBuilder, @MainWindow Stage mainWindow) { public VaultDetailUnlockedController(ObjectProperty<Vault> vault, FxApplicationWindows appWindows, VaultService vaultService, VaultStatisticsComponent.Builder vaultStatsBuilder, @MainWindow Stage mainWindow) {
@@ -33,6 +45,10 @@ public class VaultDetailUnlockedController implements FxController {
this.mainWindow = mainWindow; this.mainWindow = mainWindow;
this.vaultStats = CacheBuilder.newBuilder().weakValues().build(CacheLoader.from(this::buildVaultStats)); this.vaultStats = CacheBuilder.newBuilder().weakValues().build(CacheLoader.from(this::buildVaultStats));
this.vaultStatsBuilder = vaultStatsBuilder; 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) { private VaultStatisticsComponent buildVaultStats(Vault vault) {
@@ -44,6 +60,11 @@ public class VaultDetailUnlockedController implements FxController {
vaultService.reveal(vault.get()); vaultService.reveal(vault.get());
} }
@FXML
public void copyMountUri() {
// TODO
}
@FXML @FXML
public void lock() { public void lock() {
appWindows.startLockWorkflow(vault.get(), mainWindow); appWindows.startLockWorkflow(vault.get(), mainWindow);
@@ -64,4 +85,29 @@ public class VaultDetailUnlockedController implements FxController {
return vault.get(); return vault.get();
} }
public ObservableValue<Boolean> accessibleViaPathProperty() {
return accessibleViaPath;
}
public boolean isAccessibleViaPath() {
return accessibleViaPath.getValue();
}
public ObservableValue<Boolean> accessibleViaUriProperty() {
return accessibleViaUri;
}
public boolean isAccessibleViaUri() {
return accessibleViaUri.getValue();
}
public ObservableValue<String> mountUriProperty() {
return mountUri;
}
public String getMountUri() {
return mountUri.getValue();
}
} }

View File

@@ -12,21 +12,26 @@
alignment="TOP_CENTER" alignment="TOP_CENTER"
spacing="9"> spacing="9">
<Label text="%main.vaultDetail.accessLocation"/> <Label text="%main.vaultDetail.accessLocation"/>
<Button styleClass="button-large" contentDisplay="GRAPHIC_ONLY" minWidth="120" onAction="#revealAccessLocation" defaultButton="${controller.vault.unlocked}"> <Button styleClass="button-large" contentDisplay="GRAPHIC_ONLY" minWidth="120" onAction="#revealAccessLocation" defaultButton="${controller.accessibleViaPath}" visible="${controller.accessibleViaPath}" managed="${controller.accessibleViaPath}">
<graphic> <graphic>
<HBox spacing="12" alignment="CENTER"> <HBox spacing="12" alignment="CENTER">
<FontAwesome5IconView glyph="HDD" glyphSize="24"/> <FontAwesome5IconView glyph="HDD" glyphSize="24"/>
<VBox spacing="4" alignment="CENTER_LEFT"> <VBox spacing="4" alignment="CENTER_LEFT">
<Label text="%main.vaultDetail.revealBtn"/> <Label text="%main.vaultDetail.revealBtn"/>
<!-- TODO -->
<!--Label styleClass="label-extra-small" text="${controller.vault.accessPoint}" textOverrun="CENTER_ELLIPSIS"
visible="${controller.vault.accessPoint.empty}" managed="${controller.vault.accessPoint.empty}"/-->
</VBox> </VBox>
</HBox> </HBox>
</graphic> </graphic>
<!--tooltip> </Button>
<Tooltip text="${controller.vault.accessPoint}"/> <Button styleClass="button-large" contentDisplay="GRAPHIC_ONLY" minWidth="120" onAction="#copyMountUri" defaultButton="${controller.accessibleViaUri}" visible="${controller.accessibleViaUri}" managed="${controller.accessibleViaUri}">
</tooltip --> <graphic>
<HBox spacing="12" alignment="CENTER">
<FontAwesome5IconView glyph="LINK" glyphSize="24"/>
<VBox spacing="4" alignment="CENTER_LEFT">
<Label text="%generic.button.copy"/> <!-- TODO -->
<Label styleClass="label-extra-small" text="${controller.mountUri}" textOverrun="CENTER_ELLIPSIS"/>
</VBox>
</HBox>
</graphic>
</Button> </Button>
<Button text="%main.vaultDetail.lockBtn" minWidth="120" onAction="#lock"> <Button text="%main.vaultDetail.lockBtn" minWidth="120" onAction="#lock">
<graphic> <graphic>