diff --git a/pom.xml b/pom.xml index cea4bc575..e6f1e96e4 100644 --- a/pom.xml +++ b/pom.xml @@ -33,7 +33,7 @@ org.ow2.asm,org.apache.jackrabbit,org.apache.httpcomponents - 2.8.0 + 2.9.0-SNAPSHOT 1.5.0 1.3.0 1.2.4 diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index 4dd4242b3..f43e6599d 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -59,6 +59,7 @@ open module org.cryptomator.desktop { uses org.cryptomator.common.locationpresets.LocationPresetsProvider; uses SSLContextProvider; + uses org.cryptomator.notify.NotificationHandler; provides TrayMenuController with AwtTrayMenuController; provides Configurator with LogbackConfiguratorFactory; diff --git a/src/main/java/org/cryptomator/common/CommonsModule.java b/src/main/java/org/cryptomator/common/CommonsModule.java index a1e3c0950..a3f8f29a6 100644 --- a/src/main/java/org/cryptomator/common/CommonsModule.java +++ b/src/main/java/org/cryptomator/common/CommonsModule.java @@ -15,11 +15,14 @@ import org.cryptomator.common.vaults.VaultComponent; import org.cryptomator.common.vaults.VaultListModule; import org.cryptomator.cryptolib.common.MasterkeyFileAccess; import org.cryptomator.integrations.revealpath.RevealPathService; +import org.cryptomator.notify.Event; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.inject.Named; import javax.inject.Singleton; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.util.Comparator; @@ -128,6 +131,12 @@ public abstract class CommonsModule { return executorService; } + @Provides + @Singleton + static ObservableList provideAppEventQueue() { + return FXCollections.observableArrayList(); + } + private static void handleUncaughtExceptionInBackgroundThread(Thread thread, Throwable throwable) { LOG.error("Uncaught exception in " + thread.getName(), throwable); } diff --git a/src/main/java/org/cryptomator/common/vaults/Vault.java b/src/main/java/org/cryptomator/common/vaults/Vault.java index f857d6ba1..6d47c95f5 100644 --- a/src/main/java/org/cryptomator/common/vaults/Vault.java +++ b/src/main/java/org/cryptomator/common/vaults/Vault.java @@ -18,6 +18,7 @@ import org.cryptomator.cryptofs.CryptoFileSystemProperties; import org.cryptomator.cryptofs.CryptoFileSystemProperties.FileSystemFlags; import org.cryptomator.cryptofs.CryptoFileSystemProvider; import org.cryptomator.cryptofs.common.FileSystemCapabilityChecker; +import org.cryptomator.cryptofs.event.FilesystemEvent; import org.cryptomator.cryptolib.api.CryptoException; import org.cryptomator.cryptolib.api.MasterkeyLoader; import org.cryptomator.cryptolib.api.MasterkeyLoadingFailedException; @@ -26,6 +27,8 @@ 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.cryptomator.notify.Event; +import org.cryptomator.notify.VaultEvent; import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -41,6 +44,7 @@ import javafx.beans.property.BooleanProperty; import javafx.beans.property.ObjectProperty; import javafx.beans.property.ReadOnlyStringProperty; import javafx.beans.property.SimpleBooleanProperty; +import javafx.collections.ObservableList; import java.io.IOException; import java.nio.file.Path; import java.nio.file.Paths; @@ -74,6 +78,7 @@ public class Vault { private final ObjectBinding mountPoint; private final Mounter mounter; private final Settings settings; + private final ObservableList eventQueue; private final BooleanProperty showingStats; private final AtomicReference mountHandle = new AtomicReference<>(null); @@ -85,7 +90,9 @@ public class Vault { VaultState state, // @Named("lastKnownException") ObjectProperty lastKnownException, // VaultStats stats, // - Mounter mounter, Settings settings) { + Mounter mounter, Settings settings, // + ObservableList eventQueue + ) { this.vaultSettings = vaultSettings; this.configCache = configCache; this.cryptoFileSystem = cryptoFileSystem; @@ -102,6 +109,7 @@ public class Vault { this.mountPoint = Bindings.createObjectBinding(this::getMountPoint, state); this.mounter = mounter; this.settings = settings; + this.eventQueue = eventQueue; this.showingStats = new SimpleBooleanProperty(false); this.quickAccessEntry = new AtomicReference<>(null); } @@ -143,6 +151,7 @@ public class Vault { .withFlags(flags) // .withMaxCleartextNameLength(vaultSettings.maxCleartextFilenameLength.get()) // .withVaultConfigFilename(Constants.VAULTCONFIG_FILENAME) // + .withFilesystemEventConsumer(this::consumeVaultEvent) .build(); return CryptoFileSystemProvider.newFileSystem(getPath(), fsProps); } @@ -251,6 +260,10 @@ public class Vault { } } + private void consumeVaultEvent(FilesystemEvent e) { + eventQueue.addLast(new VaultEvent(vaultSettings.id, vaultSettings.path.get().toString(), e)); + } + // ****************************************************************************** // Observable Properties // ******************************************************************************* diff --git a/src/main/java/org/cryptomator/notify/Answer.java b/src/main/java/org/cryptomator/notify/Answer.java new file mode 100644 index 000000000..8c99b82de --- /dev/null +++ b/src/main/java/org/cryptomator/notify/Answer.java @@ -0,0 +1,14 @@ +package org.cryptomator.notify; + +public sealed interface Answer permits Answer.DoNothing, Answer.DoSomething { + + + record DoNothing() implements Answer {} + + record DoSomething(Runnable action) implements Answer { + + void run() { + action.run(); + } + } +} diff --git a/src/main/java/org/cryptomator/notify/AppEvent.java b/src/main/java/org/cryptomator/notify/AppEvent.java new file mode 100644 index 000000000..afeb829e4 --- /dev/null +++ b/src/main/java/org/cryptomator/notify/AppEvent.java @@ -0,0 +1,3 @@ +package org.cryptomator.notify; + +public record AppEvent() implements Event {} diff --git a/src/main/java/org/cryptomator/notify/Event.java b/src/main/java/org/cryptomator/notify/Event.java new file mode 100644 index 000000000..a2dda9559 --- /dev/null +++ b/src/main/java/org/cryptomator/notify/Event.java @@ -0,0 +1,5 @@ +package org.cryptomator.notify; + +public sealed interface Event permits AppEvent, VaultEvent { + +} diff --git a/src/main/java/org/cryptomator/notify/NotificationHandler.java b/src/main/java/org/cryptomator/notify/NotificationHandler.java new file mode 100644 index 000000000..48936e30b --- /dev/null +++ b/src/main/java/org/cryptomator/notify/NotificationHandler.java @@ -0,0 +1,15 @@ +package org.cryptomator.notify; + +import org.cryptomator.integrations.common.IntegrationsLoader; + +import java.util.ServiceLoader; +import java.util.stream.Stream; + +public interface NotificationHandler { + + Answer handle(Event e); + + static Stream loadAll() { + return IntegrationsLoader.loadAll(ServiceLoader.load(NotificationHandler.class), NotificationHandler.class); + } +} diff --git a/src/main/java/org/cryptomator/notify/VaultEvent.java b/src/main/java/org/cryptomator/notify/VaultEvent.java new file mode 100644 index 000000000..6c2690494 --- /dev/null +++ b/src/main/java/org/cryptomator/notify/VaultEvent.java @@ -0,0 +1,7 @@ +package org.cryptomator.notify; + +import org.cryptomator.cryptofs.event.FilesystemEvent; + +public record VaultEvent(String vaultId, String path, FilesystemEvent actualEvent) implements Event { + +} diff --git a/src/main/java/org/cryptomator/ui/eventviewer/EventViewerComponent.java b/src/main/java/org/cryptomator/ui/eventviewer/EventViewerComponent.java new file mode 100644 index 000000000..8ac56320b --- /dev/null +++ b/src/main/java/org/cryptomator/ui/eventviewer/EventViewerComponent.java @@ -0,0 +1,3 @@ +package org.cryptomator.ui.eventviewer; + +public interface EventViewerComponent {}