Browse Source

use quick access service in unlock/lock

Armin Schrenk 8 months ago
parent
commit
e5003c1783

+ 1 - 1
.github/workflows/win-exe.yml

@@ -113,7 +113,7 @@ jobs:
           --copyright "(C) 2016 - 2024 Skymatic GmbH"
           --app-version "${{ needs.get-version.outputs.semVerNum }}.${{ needs.get-version.outputs.revNum }}"
           --java-options "--enable-preview"
-          --java-options "--enable-native-access=org.cryptomator.jfuse.win"
+          --java-options "--enable-native-access=org.cryptomator.jfuse.win,org.cryptomator.integrations.win"
           --java-options "-Xss5m"
           --java-options "-Xmx256m"
           --java-options "-Dcryptomator.appVersion=\"${{ needs.get-version.outputs.semVerStr }}\""

File diff suppressed because it is too large
+ 1 - 1
.idea/runConfigurations/Cryptomator_Windows.xml


File diff suppressed because it is too large
+ 1 - 1
.idea/runConfigurations/Cryptomator_Windows_Dev.xml


+ 1 - 1
dist/win/build.ps1

@@ -100,7 +100,7 @@ if ($clean -and (Test-Path -Path $appPath)) {
 	--vendor $Vendor `
 	--copyright $copyright `
 	--java-options "--enable-preview" `
-	--java-options "--enable-native-access=org.cryptomator.jfuse.win" `
+	--java-options "--enable-native-access=org.cryptomator.jfuse.win,org.cryptomator.integrations.win" `
 	--java-options "-Xss5m" `
 	--java-options "-Xmx256m" `
 	--java-options "-Dcryptomator.appVersion=`"$semVerNo`"" `

+ 3 - 3
pom.xml

@@ -34,10 +34,10 @@
 
 		<!-- cryptomator dependencies -->
 		<cryptomator.cryptofs.version>2.6.9</cryptomator.cryptofs.version>
-		<cryptomator.integrations.version>1.3.1</cryptomator.integrations.version>
-		<cryptomator.integrations.win.version>1.2.5</cryptomator.integrations.win.version>
+		<cryptomator.integrations.version>1.4.0-beta1</cryptomator.integrations.version>
+		<cryptomator.integrations.win.version>1.2.5</cryptomator.integrations.win.version> <!-- TODO update to 1.3.0 once released -->
 		<cryptomator.integrations.mac.version>1.2.4</cryptomator.integrations.mac.version>
-		<cryptomator.integrations.linux.version>1.4.5</cryptomator.integrations.linux.version>
+		<cryptomator.integrations.linux.version>1.4.5</cryptomator.integrations.linux.version> <!-- TODO update to 1.5.0 once released -->
 		<cryptomator.fuse.version>5.0.0</cryptomator.fuse.version>
 		<cryptomator.webdav.version>2.0.6</cryptomator.webdav.version>
 

+ 7 - 0
src/main/java/org/cryptomator/common/CommonsModule.java

@@ -14,6 +14,7 @@ import org.cryptomator.common.settings.SettingsProvider;
 import org.cryptomator.common.vaults.VaultComponent;
 import org.cryptomator.common.vaults.VaultListModule;
 import org.cryptomator.cryptolib.common.MasterkeyFileAccess;
+import org.cryptomator.integrations.quickaccess.QuickAccessService;
 import org.cryptomator.integrations.revealpath.RevealPathService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -128,6 +129,12 @@ public abstract class CommonsModule {
 		return executorService;
 	}
 
+	@Provides
+	@Singleton
+	static Optional<QuickAccessService> provideQuickAccessService() {
+		return QuickAccessService.get().findFirst();
+	}
+
 	private static void handleUncaughtExceptionInBackgroundThread(Thread thread, Throwable throwable) {
 		LOG.error("Uncaught exception in " + thread.getName(), throwable);
 	}

+ 5 - 0
src/main/java/org/cryptomator/common/settings/Settings.java

@@ -41,6 +41,7 @@ public class Settings {
 	static final int DEFAULT_NUM_TRAY_NOTIFICATIONS = 3;
 	static final boolean DEFAULT_DEBUG_MODE = false;
 	static final UiTheme DEFAULT_THEME = UiTheme.LIGHT;
+	static final boolean DEFAULT_ADD_TO_QUICK_ACCESS = true;
 	@Deprecated // to be changed to "whatever is available" eventually
 	static final String DEFAULT_KEYCHAIN_PROVIDER = SystemUtils.IS_OS_WINDOWS ? "org.cryptomator.windows.keychain.WindowsProtectedKeychainAccess" : SystemUtils.IS_OS_MAC ? "org.cryptomator.macos.keychain.MacSystemKeychainAccess" : "org.cryptomator.linux.keychain.SecretServiceKeychainAccess";
 	static final String DEFAULT_USER_INTERFACE_ORIENTATION = NodeOrientation.LEFT_TO_RIGHT.name();
@@ -52,6 +53,7 @@ public class Settings {
 	public final BooleanProperty startHidden;
 	public final BooleanProperty autoCloseVaults;
 	public final BooleanProperty useKeychain;
+	public final BooleanProperty addToQuickAccess; //TODO: for now, we only support Sidebar integration per System (GNOME Nautilus for Linux)
 	public final IntegerProperty port;
 	public final IntegerProperty numTrayNotifications;
 	public final BooleanProperty debugMode;
@@ -89,6 +91,7 @@ public class Settings {
 		this.startHidden = new SimpleBooleanProperty(this, "startHidden", json.startHidden);
 		this.autoCloseVaults = new SimpleBooleanProperty(this, "autoCloseVaults", json.autoCloseVaults);
 		this.useKeychain = new SimpleBooleanProperty(this, "useKeychain", json.useKeychain);
+		this.addToQuickAccess = new SimpleBooleanProperty(this, "addToQuickAccess", json.addToQuickAccess);
 		this.port = new SimpleIntegerProperty(this, "webDavPort", json.port);
 		this.numTrayNotifications = new SimpleIntegerProperty(this, "numTrayNotifications", json.numTrayNotifications);
 		this.debugMode = new SimpleBooleanProperty(this, "debugMode", json.debugMode);
@@ -116,6 +119,7 @@ public class Settings {
 		startHidden.addListener(this::somethingChanged);
 		autoCloseVaults.addListener(this::somethingChanged);
 		useKeychain.addListener(this::somethingChanged);
+		addToQuickAccess.addListener(this::somethingChanged);
 		port.addListener(this::somethingChanged);
 		numTrayNotifications.addListener(this::somethingChanged);
 		debugMode.addListener(this::somethingChanged);
@@ -170,6 +174,7 @@ public class Settings {
 		json.startHidden = startHidden.get();
 		json.autoCloseVaults = autoCloseVaults.get();
 		json.useKeychain = useKeychain.get();
+		json.addToQuickAccess = addToQuickAccess.get();
 		json.port = port.get();
 		json.numTrayNotifications = numTrayNotifications.get();
 		json.debugMode = debugMode.get();

+ 2 - 0
src/main/java/org/cryptomator/common/settings/SettingsJson.java

@@ -86,4 +86,6 @@ class SettingsJson {
 	@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss'Z'", timezone = "UTC")
 	Instant lastSuccessfulUpdateCheck = Settings.DEFAULT_TIMESTAMP;
 
+	@JsonProperty("addToQuickAccess")
+	boolean addToQuickAccess = Settings.DEFAULT_ADD_TO_QUICK_ACCESS;
 }

+ 58 - 1
src/main/java/org/cryptomator/common/vaults/Vault.java

@@ -11,6 +11,7 @@ package org.cryptomator.common.vaults;
 import org.apache.commons.lang3.SystemUtils;
 import org.cryptomator.common.Constants;
 import org.cryptomator.common.mount.Mounter;
+import org.cryptomator.common.settings.Settings;
 import org.cryptomator.common.settings.VaultSettings;
 import org.cryptomator.cryptofs.CryptoFileSystem;
 import org.cryptomator.cryptofs.CryptoFileSystemProperties;
@@ -23,6 +24,9 @@ import org.cryptomator.cryptolib.api.MasterkeyLoadingFailedException;
 import org.cryptomator.integrations.mount.MountFailedException;
 import org.cryptomator.integrations.mount.Mountpoint;
 import org.cryptomator.integrations.mount.UnmountFailedException;
+import org.cryptomator.integrations.quickaccess.QuickAccessService;
+import org.cryptomator.integrations.quickaccess.QuickAccessServiceException;
+import org.jetbrains.annotations.NotNull;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -42,6 +46,7 @@ import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.EnumSet;
 import java.util.Objects;
+import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicReference;
 
@@ -54,6 +59,7 @@ public class Vault {
 
 	private final VaultSettings vaultSettings;
 	private final AtomicReference<CryptoFileSystem> cryptoFileSystem;
+	private final AtomicReference<QuickAccessService.QuickAccessEntry> quickAccessEntry;
 	private final VaultState state;
 	private final ObjectProperty<Exception> lastKnownException;
 	private final VaultConfigCache configCache;
@@ -67,6 +73,8 @@ public class Vault {
 	private final BooleanBinding unknownError;
 	private final ObjectBinding<Mountpoint> mountPoint;
 	private final Mounter mounter;
+	private final Settings settings;
+	private final Optional<QuickAccessService> quickAccessService;
 	private final BooleanProperty showingStats;
 
 	private final AtomicReference<Mounter.MountHandle> mountHandle = new AtomicReference<>(null);
@@ -78,7 +86,7 @@ public class Vault {
 		  VaultState state, //
 		  @Named("lastKnownException") ObjectProperty<Exception> lastKnownException, //
 		  VaultStats stats, //
-		  Mounter mounter) {
+		  Mounter mounter, Settings settings, Optional<QuickAccessService> quickAccessService) {
 		this.vaultSettings = vaultSettings;
 		this.configCache = configCache;
 		this.cryptoFileSystem = cryptoFileSystem;
@@ -94,7 +102,10 @@ public class Vault {
 		this.unknownError = Bindings.createBooleanBinding(this::isUnknownError, state);
 		this.mountPoint = Bindings.createObjectBinding(this::getMountPoint, state);
 		this.mounter = mounter;
+		this.settings = settings;
+		this.quickAccessService = quickAccessService;
 		this.showingStats = new SimpleBooleanProperty(false);
+		this.quickAccessEntry = new AtomicReference<>(null);
 	}
 
 	// ******************************************************************************
@@ -154,6 +165,9 @@ public class Vault {
 			var rootPath = fs.getRootDirectories().iterator().next();
 			var mountHandle = mounter.mount(vaultSettings, rootPath);
 			success = this.mountHandle.compareAndSet(null, mountHandle);
+			if (settings.addToQuickAccess.getValue()) {
+				addToQuickAccess();
+			}
 		} finally {
 			if (!success) {
 				destroyCryptoFileSystem();
@@ -178,6 +192,7 @@ public class Vault {
 			mountHandle.mountObj().close();
 			mountHandle.specialCleanup().run();
 		} finally {
+			removeFromSidebar();
 			destroyCryptoFileSystem();
 		}
 
@@ -185,6 +200,48 @@ public class Vault {
 		LOG.info("Locked vault '{}'", getDisplayName());
 	}
 
+	private synchronized void addToQuickAccess() {
+		if (quickAccessEntry.get() != null) {
+			//we don't throw an exception since we don't wanna block unlocking
+			LOG.warn("Vault already added to quick access area. Will be removed on next lock operation.");
+			return;
+
+		}
+		quickAccessService.ifPresentOrElse( //
+				this::addToQuickAccessInternal, //
+				() -> LOG.warn("Unable to add Vault to quick access area: No implementation available."));
+	}
+
+	private void addToQuickAccessInternal(@NotNull QuickAccessService s) {
+		if (getMountPoint() instanceof Mountpoint.WithPath mp) {
+			try {
+				var entry = s.add(mp.path(), getDisplayName());
+				quickAccessEntry.set(entry);
+			} catch (QuickAccessServiceException e) {
+				LOG.error("Adding vault to quick access area failed", e);
+			}
+		} else {
+			LOG.warn("Unable to add vault to quick access area: Vault is not mounted to local system path.");
+		}
+	}
+
+	private synchronized void removeFromSidebar() {
+		if (quickAccessEntry.get() == null) {
+			LOG.info("Removing vault from quick access area: Entry not found, nothing to do.");
+			return;
+		}
+		removeFromSidebarInternal();
+	}
+
+	private void removeFromSidebarInternal() {
+		try {
+			quickAccessEntry.get().remove();
+			quickAccessEntry.set(null);
+		} catch (QuickAccessServiceException e) {
+			LOG.error("Removing vault from quick access area failed", e);
+		}
+	}
+
 	// ******************************************************************************
 	// Observable Properties
 	// *******************************************************************************