From 6365c222971dc291a8f2a75c8d0c26546df43241 Mon Sep 17 00:00:00 2001 From: Jan-Peter Klein Date: Wed, 22 Jan 2025 16:46:18 +0100 Subject: [PATCH 001/120] add keyLoader entry to VaultSettings --- .../common/settings/VaultSettings.java | 3 +++ .../common/settings/VaultSettingsJson.java | 3 +++ .../org/cryptomator/common/vaults/Vault.java | 10 ++++++++++ .../common/vaults/VaultListManager.java | 18 ++++++++++++++++++ .../HubToPasswordConvertController.java | 2 ++ .../ui/sharevault/ShareVaultController.java | 4 ++-- .../vaultoptions/VaultOptionsController.java | 6 +++--- 7 files changed, 41 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/cryptomator/common/settings/VaultSettings.java b/src/main/java/org/cryptomator/common/settings/VaultSettings.java index fd21fc197..efc06ff18 100644 --- a/src/main/java/org/cryptomator/common/settings/VaultSettings.java +++ b/src/main/java/org/cryptomator/common/settings/VaultSettings.java @@ -58,6 +58,7 @@ public class VaultSettings { public final StringExpression mountName; public final StringProperty mountService; public final IntegerProperty port; + public final StringProperty keyLoader; VaultSettings(VaultSettingsJson json) { this.id = json.id; @@ -74,6 +75,7 @@ public class VaultSettings { this.mountPoint = new SimpleObjectProperty<>(this, "mountPoint", json.mountPoint == null ? null : Path.of(json.mountPoint)); this.mountService = new SimpleStringProperty(this, "mountService", json.mountService); this.port = new SimpleIntegerProperty(this, "port", json.port); + this.keyLoader = new SimpleStringProperty(this, "keyLoader", json.keyLoader); // mount name is no longer an explicit setting, see https://github.com/cryptomator/cryptomator/pull/1318 this.mountName = StringExpression.stringExpression(Bindings.createStringBinding(() -> { final String name; @@ -130,6 +132,7 @@ public class VaultSettings { json.mountPoint = mountPoint.map(Path::toString).getValue(); json.mountService = mountService.get(); json.port = port.get(); + json.keyLoader = keyLoader.get(); return json; } diff --git a/src/main/java/org/cryptomator/common/settings/VaultSettingsJson.java b/src/main/java/org/cryptomator/common/settings/VaultSettingsJson.java index 43aa204e8..61de7ae7b 100644 --- a/src/main/java/org/cryptomator/common/settings/VaultSettingsJson.java +++ b/src/main/java/org/cryptomator/common/settings/VaultSettingsJson.java @@ -48,6 +48,9 @@ class VaultSettingsJson { @JsonProperty("mountService") String mountService; + @JsonProperty("keyLoader") + String keyLoader; + @JsonProperty("port") int port = VaultSettings.DEFAULT_PORT; diff --git a/src/main/java/org/cryptomator/common/vaults/Vault.java b/src/main/java/org/cryptomator/common/vaults/Vault.java index f857d6ba1..182372a56 100644 --- a/src/main/java/org/cryptomator/common/vaults/Vault.java +++ b/src/main/java/org/cryptomator/common/vaults/Vault.java @@ -75,6 +75,7 @@ public class Vault { private final Mounter mounter; private final Settings settings; private final BooleanProperty showingStats; + private final StringBinding keyLoader; private final AtomicReference mountHandle = new AtomicReference<>(null); @@ -104,6 +105,7 @@ public class Vault { this.settings = settings; this.showingStats = new SimpleBooleanProperty(false); this.quickAccessEntry = new AtomicReference<>(null); + this.keyLoader = Bindings.createStringBinding(this::getKeyLoader, vaultSettings.keyLoader); } // ****************************************************************************** @@ -340,6 +342,14 @@ public class Vault { return handle == null ? null : handle.mountObj().getMountpoint(); } + public StringBinding keyLoaderProperty() { + return keyLoader; + } + + public String getKeyLoader() { + return vaultSettings.keyLoader.get(); + } + public StringBinding displayablePathProperty() { return displayablePath; } diff --git a/src/main/java/org/cryptomator/common/vaults/VaultListManager.java b/src/main/java/org/cryptomator/common/vaults/VaultListManager.java index 87faff77a..b14c8457d 100644 --- a/src/main/java/org/cryptomator/common/vaults/VaultListManager.java +++ b/src/main/java/org/cryptomator/common/vaults/VaultListManager.java @@ -27,6 +27,7 @@ import java.nio.file.NoSuchFileException; import java.nio.file.Path; import java.util.Collection; import java.util.List; +import java.util.Objects; import java.util.Optional; import java.util.ResourceBundle; @@ -73,11 +74,27 @@ public class VaultListManager { return get(normalizedPathToVault) // .orElseGet(() -> { Vault newVault = create(newVaultSettings(normalizedPathToVault)); + setVaultScheme(newVault); vaultList.add(newVault); return newVault; }); } + private void setVaultScheme(Vault vault) { + try { + var keyLoader = vault.getVaultSettings().keyLoader; + if (Objects.isNull(keyLoader.get())) { + var vaultConfig = vault.getVaultConfigCache().get(); + var keyIdScheme = vaultConfig.getKeyId().getScheme(); + keyLoader.set(keyIdScheme); + } + } catch (NoSuchFileException e) { + LOG.error("NoSuchFileException", e); + } catch (IOException e) { + throw new RuntimeException("Unexpected Exception", e); + } + } + private VaultSettings newVaultSettings(Path path) { VaultSettings vaultSettings = VaultSettings.withRandomId(); vaultSettings.path.set(path); @@ -101,6 +118,7 @@ public class VaultListManager { private void addAll(Collection vaultSettings) { Collection vaults = vaultSettings.stream().map(this::create).toList(); vaultList.addAll(vaults); + vaults.forEach(this::setVaultScheme); } private Optional get(Path vaultPath) { diff --git a/src/main/java/org/cryptomator/ui/convertvault/HubToPasswordConvertController.java b/src/main/java/org/cryptomator/ui/convertvault/HubToPasswordConvertController.java index fd6d49b89..a02c7a0b9 100644 --- a/src/main/java/org/cryptomator/ui/convertvault/HubToPasswordConvertController.java +++ b/src/main/java/org/cryptomator/ui/convertvault/HubToPasswordConvertController.java @@ -15,6 +15,7 @@ import org.cryptomator.ui.common.FxController; import org.cryptomator.ui.common.FxmlFile; import org.cryptomator.ui.common.FxmlScene; import org.cryptomator.ui.fxapp.FxApplicationWindows; +import org.cryptomator.ui.keyloading.masterkeyfile.MasterkeyFileLoadingStrategy; import org.cryptomator.ui.recoverykey.RecoveryKeyFactory; import org.jetbrains.annotations.VisibleForTesting; import org.slf4j.Logger; @@ -108,6 +109,7 @@ public class HubToPasswordConvertController implements FxController { .thenRunAsync(this::convertInternal, backgroundExecutorService) // .whenCompleteAsync((result, exception) -> { if (exception == null) { + vault.getVaultSettings().keyLoader.set(MasterkeyFileLoadingStrategy.SCHEME); LOG.info("Conversion of vault {} succeeded.", vault.getPath()); window.setScene(successScene.get()); } else { diff --git a/src/main/java/org/cryptomator/ui/sharevault/ShareVaultController.java b/src/main/java/org/cryptomator/ui/sharevault/ShareVaultController.java index 63230cbbf..37202d2de 100644 --- a/src/main/java/org/cryptomator/ui/sharevault/ShareVaultController.java +++ b/src/main/java/org/cryptomator/ui/sharevault/ShareVaultController.java @@ -33,8 +33,8 @@ public class ShareVaultController implements FxController { this.window = window; this.application = application; this.vault = vault; - var vaultScheme = vault.getVaultConfigCache().getUnchecked().getKeyId().getScheme(); - this.hubVault = (vaultScheme.equals(HubKeyLoadingStrategy.SCHEME_HUB_HTTP) || vaultScheme.equals(HubKeyLoadingStrategy.SCHEME_HUB_HTTPS)); + var vaultKeyLoader = vault.getVaultSettings().keyLoader.get(); + this.hubVault = (vaultKeyLoader.equals(HubKeyLoadingStrategy.SCHEME_HUB_HTTP) || vaultKeyLoader.equals(HubKeyLoadingStrategy.SCHEME_HUB_HTTPS)); } @FXML diff --git a/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsController.java b/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsController.java index 78d228995..aa8bfcd9b 100644 --- a/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsController.java +++ b/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsController.java @@ -42,11 +42,11 @@ public class VaultOptionsController implements FxController { window.setOnShowing(this::windowWillAppear); selectedTabProperty.addListener(observable -> this.selectChosenTab()); tabPane.getSelectionModel().selectedItemProperty().addListener(observable -> this.selectedTabChanged()); - var vaultScheme = vault.getVaultConfigCache().getUnchecked().getKeyId().getScheme(); - if(!vaultScheme.equals(MasterkeyFileLoadingStrategy.SCHEME)){ + var vaultKeyLoader = vault.getVaultSettings().keyLoader.get(); + if(!vaultKeyLoader.equals(MasterkeyFileLoadingStrategy.SCHEME)){ tabPane.getTabs().remove(keyTab); } - if(!(vaultScheme.equals(HubKeyLoadingStrategy.SCHEME_HUB_HTTP) || vaultScheme.equals(HubKeyLoadingStrategy.SCHEME_HUB_HTTPS))){ + if(!(vaultKeyLoader.equals(HubKeyLoadingStrategy.SCHEME_HUB_HTTP) || vaultKeyLoader.equals(HubKeyLoadingStrategy.SCHEME_HUB_HTTPS))){ tabPane.getTabs().remove(hubTab); } From b25b5bd5a3dee00b40349ac9eff55c4cb1bd71be Mon Sep 17 00:00:00 2001 From: Jan-Peter Klein Date: Wed, 22 Jan 2025 16:59:52 +0100 Subject: [PATCH 002/120] add keyLoader to observables --- .../java/org/cryptomator/common/settings/VaultSettings.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/cryptomator/common/settings/VaultSettings.java b/src/main/java/org/cryptomator/common/settings/VaultSettings.java index efc06ff18..b211b356b 100644 --- a/src/main/java/org/cryptomator/common/settings/VaultSettings.java +++ b/src/main/java/org/cryptomator/common/settings/VaultSettings.java @@ -101,7 +101,7 @@ public class VaultSettings { } Observable[] observables() { - return new Observable[]{actionAfterUnlock, autoLockIdleSeconds, autoLockWhenIdle, displayName, maxCleartextFilenameLength, mountFlags, mountPoint, path, revealAfterMount, unlockAfterStartup, usesReadOnlyMode, port, mountService}; + return new Observable[]{actionAfterUnlock, autoLockIdleSeconds, autoLockWhenIdle, displayName, maxCleartextFilenameLength, mountFlags, mountPoint, path, revealAfterMount, unlockAfterStartup, usesReadOnlyMode, port, mountService, keyLoader}; } public static VaultSettings withRandomId() { From ba34cfa9d59a05c3562297fc1270c7a4066882fc Mon Sep 17 00:00:00 2001 From: Jan-Peter Klein Date: Mon, 10 Feb 2025 12:07:25 +0100 Subject: [PATCH 003/120] renamed to lastKnownKeyLoader --- .../cryptomator/common/settings/VaultSettings.java | 8 ++++---- .../common/settings/VaultSettingsJson.java | 4 ++-- .../java/org/cryptomator/common/vaults/Vault.java | 12 ++++++------ .../cryptomator/common/vaults/VaultListManager.java | 6 +++--- .../convertvault/HubToPasswordConvertController.java | 2 +- .../ui/sharevault/ShareVaultController.java | 2 +- .../ui/vaultoptions/VaultOptionsController.java | 2 +- 7 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/main/java/org/cryptomator/common/settings/VaultSettings.java b/src/main/java/org/cryptomator/common/settings/VaultSettings.java index b211b356b..5112415b4 100644 --- a/src/main/java/org/cryptomator/common/settings/VaultSettings.java +++ b/src/main/java/org/cryptomator/common/settings/VaultSettings.java @@ -58,7 +58,7 @@ public class VaultSettings { public final StringExpression mountName; public final StringProperty mountService; public final IntegerProperty port; - public final StringProperty keyLoader; + public final StringProperty lastKnownKeyLoader; VaultSettings(VaultSettingsJson json) { this.id = json.id; @@ -75,7 +75,7 @@ public class VaultSettings { this.mountPoint = new SimpleObjectProperty<>(this, "mountPoint", json.mountPoint == null ? null : Path.of(json.mountPoint)); this.mountService = new SimpleStringProperty(this, "mountService", json.mountService); this.port = new SimpleIntegerProperty(this, "port", json.port); - this.keyLoader = new SimpleStringProperty(this, "keyLoader", json.keyLoader); + this.lastKnownKeyLoader = new SimpleStringProperty(this, "lastKnownKeyLoader", json.lastKnownKeyLoader); // mount name is no longer an explicit setting, see https://github.com/cryptomator/cryptomator/pull/1318 this.mountName = StringExpression.stringExpression(Bindings.createStringBinding(() -> { final String name; @@ -101,7 +101,7 @@ public class VaultSettings { } Observable[] observables() { - return new Observable[]{actionAfterUnlock, autoLockIdleSeconds, autoLockWhenIdle, displayName, maxCleartextFilenameLength, mountFlags, mountPoint, path, revealAfterMount, unlockAfterStartup, usesReadOnlyMode, port, mountService, keyLoader}; + return new Observable[]{actionAfterUnlock, autoLockIdleSeconds, autoLockWhenIdle, displayName, maxCleartextFilenameLength, mountFlags, mountPoint, path, revealAfterMount, unlockAfterStartup, usesReadOnlyMode, port, mountService, lastKnownKeyLoader}; } public static VaultSettings withRandomId() { @@ -132,7 +132,7 @@ public class VaultSettings { json.mountPoint = mountPoint.map(Path::toString).getValue(); json.mountService = mountService.get(); json.port = port.get(); - json.keyLoader = keyLoader.get(); + json.lastKnownKeyLoader = lastKnownKeyLoader.get(); return json; } diff --git a/src/main/java/org/cryptomator/common/settings/VaultSettingsJson.java b/src/main/java/org/cryptomator/common/settings/VaultSettingsJson.java index 61de7ae7b..870b74e07 100644 --- a/src/main/java/org/cryptomator/common/settings/VaultSettingsJson.java +++ b/src/main/java/org/cryptomator/common/settings/VaultSettingsJson.java @@ -48,8 +48,8 @@ class VaultSettingsJson { @JsonProperty("mountService") String mountService; - @JsonProperty("keyLoader") - String keyLoader; + @JsonProperty("lastKnownKeyLoader") + String lastKnownKeyLoader; @JsonProperty("port") int port = VaultSettings.DEFAULT_PORT; diff --git a/src/main/java/org/cryptomator/common/vaults/Vault.java b/src/main/java/org/cryptomator/common/vaults/Vault.java index 182372a56..7605b9f34 100644 --- a/src/main/java/org/cryptomator/common/vaults/Vault.java +++ b/src/main/java/org/cryptomator/common/vaults/Vault.java @@ -75,7 +75,7 @@ public class Vault { private final Mounter mounter; private final Settings settings; private final BooleanProperty showingStats; - private final StringBinding keyLoader; + private final StringBinding lastKnownKeyLoader; private final AtomicReference mountHandle = new AtomicReference<>(null); @@ -105,7 +105,7 @@ public class Vault { this.settings = settings; this.showingStats = new SimpleBooleanProperty(false); this.quickAccessEntry = new AtomicReference<>(null); - this.keyLoader = Bindings.createStringBinding(this::getKeyLoader, vaultSettings.keyLoader); + this.lastKnownKeyLoader = Bindings.createStringBinding(this::getLastKnownKeyLoader, vaultSettings.lastKnownKeyLoader); } // ****************************************************************************** @@ -342,12 +342,12 @@ public class Vault { return handle == null ? null : handle.mountObj().getMountpoint(); } - public StringBinding keyLoaderProperty() { - return keyLoader; + public StringBinding lastKnownKeyLoaderProperty() { + return lastKnownKeyLoader; } - public String getKeyLoader() { - return vaultSettings.keyLoader.get(); + public String getLastKnownKeyLoader() { + return vaultSettings.lastKnownKeyLoader.get(); } public StringBinding displayablePathProperty() { diff --git a/src/main/java/org/cryptomator/common/vaults/VaultListManager.java b/src/main/java/org/cryptomator/common/vaults/VaultListManager.java index b14c8457d..944c7573d 100644 --- a/src/main/java/org/cryptomator/common/vaults/VaultListManager.java +++ b/src/main/java/org/cryptomator/common/vaults/VaultListManager.java @@ -82,11 +82,11 @@ public class VaultListManager { private void setVaultScheme(Vault vault) { try { - var keyLoader = vault.getVaultSettings().keyLoader; - if (Objects.isNull(keyLoader.get())) { + var lastKnownKeyLoader = vault.getVaultSettings().lastKnownKeyLoader; + if (Objects.isNull(lastKnownKeyLoader.get())) { var vaultConfig = vault.getVaultConfigCache().get(); var keyIdScheme = vaultConfig.getKeyId().getScheme(); - keyLoader.set(keyIdScheme); + lastKnownKeyLoader.set(keyIdScheme); } } catch (NoSuchFileException e) { LOG.error("NoSuchFileException", e); diff --git a/src/main/java/org/cryptomator/ui/convertvault/HubToPasswordConvertController.java b/src/main/java/org/cryptomator/ui/convertvault/HubToPasswordConvertController.java index a02c7a0b9..dc95f7051 100644 --- a/src/main/java/org/cryptomator/ui/convertvault/HubToPasswordConvertController.java +++ b/src/main/java/org/cryptomator/ui/convertvault/HubToPasswordConvertController.java @@ -109,7 +109,7 @@ public class HubToPasswordConvertController implements FxController { .thenRunAsync(this::convertInternal, backgroundExecutorService) // .whenCompleteAsync((result, exception) -> { if (exception == null) { - vault.getVaultSettings().keyLoader.set(MasterkeyFileLoadingStrategy.SCHEME); + vault.getVaultSettings().lastKnownKeyLoader.set(MasterkeyFileLoadingStrategy.SCHEME); LOG.info("Conversion of vault {} succeeded.", vault.getPath()); window.setScene(successScene.get()); } else { diff --git a/src/main/java/org/cryptomator/ui/sharevault/ShareVaultController.java b/src/main/java/org/cryptomator/ui/sharevault/ShareVaultController.java index 37202d2de..6e386fd77 100644 --- a/src/main/java/org/cryptomator/ui/sharevault/ShareVaultController.java +++ b/src/main/java/org/cryptomator/ui/sharevault/ShareVaultController.java @@ -33,7 +33,7 @@ public class ShareVaultController implements FxController { this.window = window; this.application = application; this.vault = vault; - var vaultKeyLoader = vault.getVaultSettings().keyLoader.get(); + var vaultKeyLoader = vault.getVaultSettings().lastKnownKeyLoader.get(); this.hubVault = (vaultKeyLoader.equals(HubKeyLoadingStrategy.SCHEME_HUB_HTTP) || vaultKeyLoader.equals(HubKeyLoadingStrategy.SCHEME_HUB_HTTPS)); } diff --git a/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsController.java b/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsController.java index aa8bfcd9b..26d28a972 100644 --- a/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsController.java +++ b/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsController.java @@ -42,7 +42,7 @@ public class VaultOptionsController implements FxController { window.setOnShowing(this::windowWillAppear); selectedTabProperty.addListener(observable -> this.selectChosenTab()); tabPane.getSelectionModel().selectedItemProperty().addListener(observable -> this.selectedTabChanged()); - var vaultKeyLoader = vault.getVaultSettings().keyLoader.get(); + var vaultKeyLoader = vault.getVaultSettings().lastKnownKeyLoader.get(); if(!vaultKeyLoader.equals(MasterkeyFileLoadingStrategy.SCHEME)){ tabPane.getTabs().remove(keyTab); } From 126004b1f81e1a7d28a1d6ec604ec8bae90106fa Mon Sep 17 00:00:00 2001 From: Jan-Peter Klein Date: Mon, 10 Feb 2025 12:58:54 +0100 Subject: [PATCH 004/120] improve error handling --- .../common/vaults/VaultListManager.java | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/cryptomator/common/vaults/VaultListManager.java b/src/main/java/org/cryptomator/common/vaults/VaultListManager.java index 944c7573d..2e9173a22 100644 --- a/src/main/java/org/cryptomator/common/vaults/VaultListManager.java +++ b/src/main/java/org/cryptomator/common/vaults/VaultListManager.java @@ -74,13 +74,17 @@ public class VaultListManager { return get(normalizedPathToVault) // .orElseGet(() -> { Vault newVault = create(newVaultSettings(normalizedPathToVault)); - setVaultScheme(newVault); + try { + setVaultScheme(newVault); + } catch (IOException e) { + throw new RuntimeException(e); + } vaultList.add(newVault); return newVault; }); } - private void setVaultScheme(Vault vault) { + private void setVaultScheme(Vault vault) throws IOException { try { var lastKnownKeyLoader = vault.getVaultSettings().lastKnownKeyLoader; if (Objects.isNull(lastKnownKeyLoader.get())) { @@ -89,9 +93,12 @@ public class VaultListManager { lastKnownKeyLoader.set(keyIdScheme); } } catch (NoSuchFileException e) { - LOG.error("NoSuchFileException", e); + vault.stateProperty().set(VaultState.Value.ERROR); + LOG.error("Configuration file missing or corrupted.", e); } catch (IOException e) { - throw new RuntimeException("Unexpected Exception", e); + vault.stateProperty().set(VaultState.Value.ERROR); + LOG.error("Unexpected IO exception while setting vault scheme.", e); + throw new IOException("Configuration file missing or corrupted.", e); } } @@ -118,7 +125,13 @@ public class VaultListManager { private void addAll(Collection vaultSettings) { Collection vaults = vaultSettings.stream().map(this::create).toList(); vaultList.addAll(vaults); - vaults.forEach(this::setVaultScheme); + for (Vault vault : vaults) { + try { + setVaultScheme(vault); + } catch (IOException e) { + throw new RuntimeException(e); + } + } } private Optional get(Path vaultPath) { From 6b43881909b02be9a5dff53629fa0e3087d50ed5 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Mon, 10 Feb 2025 17:07:40 +0100 Subject: [PATCH 005/120] [skip ci] update screenshot url in metainfo file --- dist/linux/common/org.cryptomator.Cryptomator.metainfo.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dist/linux/common/org.cryptomator.Cryptomator.metainfo.xml b/dist/linux/common/org.cryptomator.Cryptomator.metainfo.xml index 450f6adb2..c91a3db6e 100644 --- a/dist/linux/common/org.cryptomator.Cryptomator.metainfo.xml +++ b/dist/linux/common/org.cryptomator.Cryptomator.metainfo.xml @@ -48,7 +48,7 @@ Dark theme available - https://static.cryptomator.org/desktop/flathubScreenshots/MainWindowUnlock_dark.png + https://static.cryptomator.org/desktop/flathubScreenshots/MainWindowUnlocked_dark.png Uses AES-GCM 256 - an industry standardized, quantum resistant encryption From 664158eb84d27f68f7f9c128a763c1492fbb36d9 Mon Sep 17 00:00:00 2001 From: Jan-Peter Klein Date: Mon, 10 Feb 2025 18:09:03 +0100 Subject: [PATCH 006/120] add isHubVault method to KeyLoadingStrategy --- .../ui/keyloading/KeyLoadingStrategy.java | 15 +++++++++++++++ .../ui/sharevault/ShareVaultController.java | 5 ++--- .../ui/vaultoptions/VaultOptionsController.java | 3 ++- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/cryptomator/ui/keyloading/KeyLoadingStrategy.java b/src/main/java/org/cryptomator/ui/keyloading/KeyLoadingStrategy.java index f3f0aff8e..9835724ea 100644 --- a/src/main/java/org/cryptomator/ui/keyloading/KeyLoadingStrategy.java +++ b/src/main/java/org/cryptomator/ui/keyloading/KeyLoadingStrategy.java @@ -3,6 +3,7 @@ package org.cryptomator.ui.keyloading; import org.cryptomator.cryptolib.api.Masterkey; import org.cryptomator.cryptolib.api.MasterkeyLoader; import org.cryptomator.cryptolib.api.MasterkeyLoadingFailedException; +import org.cryptomator.ui.keyloading.hub.HubKeyLoadingStrategy; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -28,6 +29,20 @@ public interface KeyLoadingStrategy extends MasterkeyLoader { @Override Masterkey loadKey(URI keyId) throws MasterkeyLoadingFailedException; + /** + * Determines whether the provided key loader scheme corresponds to a Hub Vault. + *

+ * This method compares the {@code keyLoader} parameter with the known Hub Vault schemes + * {@link HubKeyLoadingStrategy#SCHEME_HUB_HTTP} and {@link HubKeyLoadingStrategy#SCHEME_HUB_HTTPS}. + * + * @param keyLoader A string representing the key loader scheme to be checked. + * @return {@code true} if the given key loader scheme represents a Hub Vault; {@code false} otherwise. + */ + static boolean isHubVault(String keyLoader) { + return keyLoader.equals(HubKeyLoadingStrategy.SCHEME_HUB_HTTP) || + keyLoader.equals(HubKeyLoadingStrategy.SCHEME_HUB_HTTPS); + } + /** * Allows the loader to try and recover from an exception thrown during the last attempt. * diff --git a/src/main/java/org/cryptomator/ui/sharevault/ShareVaultController.java b/src/main/java/org/cryptomator/ui/sharevault/ShareVaultController.java index 6e386fd77..859c9e38d 100644 --- a/src/main/java/org/cryptomator/ui/sharevault/ShareVaultController.java +++ b/src/main/java/org/cryptomator/ui/sharevault/ShareVaultController.java @@ -3,7 +3,7 @@ package org.cryptomator.ui.sharevault; import dagger.Lazy; import org.cryptomator.common.vaults.Vault; import org.cryptomator.ui.common.FxController; -import org.cryptomator.ui.keyloading.hub.HubKeyLoadingStrategy; +import org.cryptomator.ui.keyloading.KeyLoadingStrategy; import javax.inject.Inject; import javafx.application.Application; @@ -33,8 +33,7 @@ public class ShareVaultController implements FxController { this.window = window; this.application = application; this.vault = vault; - var vaultKeyLoader = vault.getVaultSettings().lastKnownKeyLoader.get(); - this.hubVault = (vaultKeyLoader.equals(HubKeyLoadingStrategy.SCHEME_HUB_HTTP) || vaultKeyLoader.equals(HubKeyLoadingStrategy.SCHEME_HUB_HTTPS)); + this.hubVault = KeyLoadingStrategy.isHubVault(vault.getVaultSettings().lastKnownKeyLoader.get()); } @FXML diff --git a/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsController.java b/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsController.java index 26d28a972..cf803f915 100644 --- a/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsController.java +++ b/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsController.java @@ -3,6 +3,7 @@ package org.cryptomator.ui.vaultoptions; import org.cryptomator.common.vaults.Vault; import org.cryptomator.common.vaults.VaultState; import org.cryptomator.ui.common.FxController; +import org.cryptomator.ui.keyloading.KeyLoadingStrategy; import org.cryptomator.ui.keyloading.hub.HubKeyLoadingStrategy; import org.cryptomator.ui.keyloading.masterkeyfile.MasterkeyFileLoadingStrategy; import org.slf4j.Logger; @@ -46,7 +47,7 @@ public class VaultOptionsController implements FxController { if(!vaultKeyLoader.equals(MasterkeyFileLoadingStrategy.SCHEME)){ tabPane.getTabs().remove(keyTab); } - if(!(vaultKeyLoader.equals(HubKeyLoadingStrategy.SCHEME_HUB_HTTP) || vaultKeyLoader.equals(HubKeyLoadingStrategy.SCHEME_HUB_HTTPS))){ + if(!KeyLoadingStrategy.isHubVault(vaultKeyLoader)){ tabPane.getTabs().remove(hubTab); } From a810eff797381bef77b9731988f894e72aea394e Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Mon, 10 Feb 2025 18:27:06 +0100 Subject: [PATCH 007/120] make menu buttons in vault list appear clickable --- .../ui/mainwindow/VaultListController.java | 3 ++- src/main/resources/css/dark_theme.css | 22 ++++++++++++++++-- src/main/resources/css/light_theme.css | 18 +++++++++++++++ src/main/resources/fxml/vault_list.fxml | 23 +++++++++---------- 4 files changed, 51 insertions(+), 15 deletions(-) diff --git a/src/main/java/org/cryptomator/ui/mainwindow/VaultListController.java b/src/main/java/org/cryptomator/ui/mainwindow/VaultListController.java index e353fe8ed..0c2c46204 100644 --- a/src/main/java/org/cryptomator/ui/mainwindow/VaultListController.java +++ b/src/main/java/org/cryptomator/ui/mainwindow/VaultListController.java @@ -26,6 +26,7 @@ import javafx.collections.ListChangeListener; import javafx.collections.ObservableList; import javafx.fxml.FXML; import javafx.geometry.Side; +import javafx.scene.control.Button; import javafx.scene.control.ContextMenu; import javafx.scene.control.ListView; import javafx.scene.input.ContextMenuEvent; @@ -76,7 +77,7 @@ public class VaultListController implements FxController { public ListView vaultList; public StackPane root; @FXML - private HBox addVaultButton; + private Button addVaultButton; @FXML private ContextMenu addVaultContextMenu; diff --git a/src/main/resources/css/dark_theme.css b/src/main/resources/css/dark_theme.css index dae0d1898..72e732f36 100644 --- a/src/main/resources/css/dark_theme.css +++ b/src/main/resources/css/dark_theme.css @@ -183,19 +183,37 @@ } .main-window .button-bar { + -fx-min-height:44px; + -fx-max-height:44px; -fx-background-color: MAIN_BG; -fx-border-color: CONTROL_BORDER_NORMAL transparent transparent transparent; -fx-border-width: 1px 0 0 0; } -.main-window .button-left { +.main-window .button-bar .button-left { -fx-border-color: CONTROL_BORDER_NORMAL; -fx-border-width: 0 1px 0 0; + -fx-background-color: MAIN_BG; + -fx-background-radius: 0px; + -fx-min-height: 44px; + -fx-max-height: 44px; } -.main-window .button-right { +.main-window .button-bar .button-right { -fx-border-color: CONTROL_BORDER_NORMAL; -fx-border-width: 0 0 0 1px; + -fx-background-color: MAIN_BG; + -fx-background-radius: 0px; + -fx-min-height: 44px; + -fx-max-height: 44px; +} + +.main-window .button-bar .button-left:armed { + -fx-background-color: CONTROL_BORDER_NORMAL, CONTROL_BG_ARMED; +} + +.main-window .button-bar .button-right:armed { + -fx-background-color: CONTROL_BORDER_NORMAL, CONTROL_BG_ARMED; } /******************************************************************************* diff --git a/src/main/resources/css/light_theme.css b/src/main/resources/css/light_theme.css index 84df05b10..76d14c239 100644 --- a/src/main/resources/css/light_theme.css +++ b/src/main/resources/css/light_theme.css @@ -182,6 +182,8 @@ } .main-window .button-bar { + -fx-min-height:44px; + -fx-max-height:44px; -fx-background-color: MAIN_BG; -fx-border-color: CONTROL_BORDER_NORMAL transparent transparent transparent; -fx-border-width: 1px 0 0 0; @@ -190,11 +192,27 @@ .main-window .button-bar .button-left { -fx-border-color: CONTROL_BORDER_NORMAL; -fx-border-width: 0 1px 0 0; + -fx-background-color: MAIN_BG; + -fx-background-radius: 0px; + -fx-min-height: 44px; + -fx-max-height: 44px; } .main-window .button-bar .button-right { -fx-border-color: CONTROL_BORDER_NORMAL; -fx-border-width: 0 0 0 1px; + -fx-background-color: MAIN_BG; + -fx-background-radius: 0px; + -fx-min-height: 44px; + -fx-max-height: 44px; +} + +.main-window .button-bar .button-left:armed { + -fx-background-color: CONTROL_BORDER_NORMAL, CONTROL_BG_ARMED; +} + +.main-window .button-bar .button-right:armed { + -fx-background-color: CONTROL_BORDER_NORMAL, CONTROL_BG_ARMED; } /******************************************************************************* diff --git a/src/main/resources/fxml/vault_list.fxml b/src/main/resources/fxml/vault_list.fxml index 267148d3e..161a29e87 100644 --- a/src/main/resources/fxml/vault_list.fxml +++ b/src/main/resources/fxml/vault_list.fxml @@ -11,6 +11,7 @@ + - - - - - - + - - - - - - + From 5ef666154e56e07312595cac744b67c1edd459ac Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Tue, 11 Feb 2025 10:16:15 +0100 Subject: [PATCH 008/120] use correct height in css [skip ci] --- src/main/resources/css/dark_theme.css | 12 ++++++------ src/main/resources/css/light_theme.css | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/main/resources/css/dark_theme.css b/src/main/resources/css/dark_theme.css index 72e732f36..abb6efe57 100644 --- a/src/main/resources/css/dark_theme.css +++ b/src/main/resources/css/dark_theme.css @@ -183,8 +183,8 @@ } .main-window .button-bar { - -fx-min-height:44px; - -fx-max-height:44px; + -fx-min-height:42px; + -fx-max-height:42px; -fx-background-color: MAIN_BG; -fx-border-color: CONTROL_BORDER_NORMAL transparent transparent transparent; -fx-border-width: 1px 0 0 0; @@ -195,8 +195,8 @@ -fx-border-width: 0 1px 0 0; -fx-background-color: MAIN_BG; -fx-background-radius: 0px; - -fx-min-height: 44px; - -fx-max-height: 44px; + -fx-min-height: 42px; + -fx-max-height: 42px; } .main-window .button-bar .button-right { @@ -204,8 +204,8 @@ -fx-border-width: 0 0 0 1px; -fx-background-color: MAIN_BG; -fx-background-radius: 0px; - -fx-min-height: 44px; - -fx-max-height: 44px; + -fx-min-height: 42px; + -fx-max-height: 42px; } .main-window .button-bar .button-left:armed { diff --git a/src/main/resources/css/light_theme.css b/src/main/resources/css/light_theme.css index 76d14c239..516dd0b26 100644 --- a/src/main/resources/css/light_theme.css +++ b/src/main/resources/css/light_theme.css @@ -182,8 +182,8 @@ } .main-window .button-bar { - -fx-min-height:44px; - -fx-max-height:44px; + -fx-min-height:42px; + -fx-max-height:42px; -fx-background-color: MAIN_BG; -fx-border-color: CONTROL_BORDER_NORMAL transparent transparent transparent; -fx-border-width: 1px 0 0 0; @@ -194,8 +194,8 @@ -fx-border-width: 0 1px 0 0; -fx-background-color: MAIN_BG; -fx-background-radius: 0px; - -fx-min-height: 44px; - -fx-max-height: 44px; + -fx-min-height: 42px; + -fx-max-height: 42px; } .main-window .button-bar .button-right { @@ -203,8 +203,8 @@ -fx-border-width: 0 0 0 1px; -fx-background-color: MAIN_BG; -fx-background-radius: 0px; - -fx-min-height: 44px; - -fx-max-height: 44px; + -fx-min-height: 42px; + -fx-max-height: 42px; } .main-window .button-bar .button-left:armed { From 31482d7d18e8e8f7143614e541f6fad94a5161f4 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Tue, 11 Feb 2025 12:37:30 +0100 Subject: [PATCH 009/120] [skip ci] update ide files --- .idea/compiler.xml | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/.idea/compiler.xml b/.idea/compiler.xml index be1033a0e..1256745d3 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -39,31 +39,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - From dcd7077b085ac54c7887d0b2e79e80fd60725306 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Tue, 11 Feb 2025 15:24:36 +0100 Subject: [PATCH 010/120] Feature: readd out of bounds check (#3729) references #3091 --- .../ui/mainwindow/MainWindowController.java | 68 ++++++++++++------- 1 file changed, 44 insertions(+), 24 deletions(-) diff --git a/src/main/java/org/cryptomator/ui/mainwindow/MainWindowController.java b/src/main/java/org/cryptomator/ui/mainwindow/MainWindowController.java index 999ff7882..13412dd27 100644 --- a/src/main/java/org/cryptomator/ui/mainwindow/MainWindowController.java +++ b/src/main/java/org/cryptomator/ui/mainwindow/MainWindowController.java @@ -1,13 +1,5 @@ package org.cryptomator.ui.mainwindow; -import javafx.beans.Observable; -import javafx.beans.binding.BooleanBinding; -import javafx.beans.property.ObjectProperty; -import javafx.beans.property.ReadOnlyBooleanProperty; -import javafx.beans.property.ReadOnlyObjectProperty; -import javafx.fxml.FXML; -import javafx.scene.layout.StackPane; -import javafx.stage.Stage; import org.apache.commons.lang3.SystemUtils; import org.cryptomator.common.LicenseHolder; import org.cryptomator.common.settings.Settings; @@ -21,6 +13,15 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.inject.Inject; +import javafx.beans.Observable; +import javafx.beans.binding.BooleanBinding; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.ReadOnlyBooleanProperty; +import javafx.beans.property.ReadOnlyObjectProperty; +import javafx.fxml.FXML; +import javafx.scene.layout.StackPane; +import javafx.stage.Screen; +import javafx.stage.Stage; @MainWindowScoped public class MainWindowController implements FxController { @@ -63,27 +64,46 @@ public class MainWindowController implements FxController { } window.focusedProperty().addListener(this::mainWindowFocusChanged); - if (!neverTouched()) { - window.setHeight(settings.windowHeight.get() > window.getMinHeight() ? settings.windowHeight.get() : window.getMinHeight()); - window.setWidth(settings.windowWidth.get() > window.getMinWidth() ? settings.windowWidth.get() : window.getMinWidth()); - window.setX(settings.windowXPosition.get()); - window.setY(settings.windowYPosition.get()); + int x = settings.windowXPosition.get(); + int y = settings.windowYPosition.get(); + int width = settings.windowWidth.get(); + int height = settings.windowHeight.get(); + if (windowPositionSaved(x, y, width, height) ) { + if(isWithinDisplayBounds(x, y, width, height)) { //use stored window position + window.setX(x); + window.setY(y); + window.setWidth(Math.clamp(width, window.getMinWidth(), window.getMaxWidth())); + window.setHeight(Math.clamp(height, window.getMinHeight(), window.getMaxHeight())); + } else if(isWithinDisplayBounds((int) window.getX(), (int) window.getY(), width, height)) { //just reset position of upper left corner, keep window size + window.setWidth(Math.clamp(width, window.getMinWidth(), window.getMaxWidth())); + window.setHeight(Math.clamp(height, window.getMinHeight(), window.getMaxHeight())); + } //else reset window completely } - window.widthProperty().addListener((_, _, _) -> savePositionalSettings()); - window.heightProperty().addListener((_, _, _) -> savePositionalSettings()); - window.xProperty().addListener((_, _, _) -> savePositionalSettings()); - window.yProperty().addListener((_, _, _) -> savePositionalSettings()); + + settings.windowXPosition.bind(window.xProperty()); + settings.windowYPosition.bind(window.yProperty()); + settings.windowWidth.bind(window.widthProperty()); + settings.windowHeight.bind(window.heightProperty()); } - private boolean neverTouched() { - return (settings.windowHeight.get() == 0) && (settings.windowWidth.get() == 0) && (settings.windowXPosition.get() == 0) && (settings.windowYPosition.get() == 0); + private boolean windowPositionSaved(int x, int y, int width, int height) { + return x != 0 || y != 0 || width != 0 || height != 0; } - public void savePositionalSettings() { - settings.windowWidth.setValue(window.getWidth()); - settings.windowHeight.setValue(window.getHeight()); - settings.windowXPosition.setValue(window.getX()); - settings.windowYPosition.setValue(window.getY()); + private boolean isWithinDisplayBounds(int x, int y, int width, int height) { + // define a rect which is inset on all sides from the window's rect: + final int shrinkedX = x + 20; // 20px left + final int shrinkedY = y + 5; // 5px top + final int shrinkedWidth = width - 40; // 20px left + 20px right + final int shrinkedHeigth = height - 25; // 5px top + 20px bottom + return isRectangleWithinBounds(shrinkedX, shrinkedY, 0, shrinkedHeigth) // Left pixel column + && isRectangleWithinBounds(shrinkedX + shrinkedWidth, shrinkedY, 0, shrinkedHeigth) // Right pixel column + && isRectangleWithinBounds(shrinkedX, shrinkedY, shrinkedWidth, 0) // Top pixel row + && isRectangleWithinBounds(shrinkedX, shrinkedY + shrinkedHeigth, shrinkedWidth, 0); // Bottom pixel row + } + + private boolean isRectangleWithinBounds(int x, int y, int width, int height) { + return !Screen.getScreensForRectangle(x, y, width, height).isEmpty(); } private void mainWindowFocusChanged(Observable observable) { From ca2f80024a4dd39a406f3a5668db3f03289e75b0 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Tue, 11 Feb 2025 15:38:18 +0100 Subject: [PATCH 011/120] impl draft --- pom.xml | 2 +- src/main/java/module-info.java | 1 + .../org/cryptomator/common/CommonsModule.java | 9 +++++++++ .../java/org/cryptomator/common/vaults/Vault.java | 15 ++++++++++++++- src/main/java/org/cryptomator/notify/Answer.java | 14 ++++++++++++++ .../java/org/cryptomator/notify/AppEvent.java | 3 +++ src/main/java/org/cryptomator/notify/Event.java | 5 +++++ .../cryptomator/notify/NotificationHandler.java | 15 +++++++++++++++ .../java/org/cryptomator/notify/VaultEvent.java | 7 +++++++ .../ui/eventviewer/EventViewerComponent.java | 3 +++ 10 files changed, 72 insertions(+), 2 deletions(-) create mode 100644 src/main/java/org/cryptomator/notify/Answer.java create mode 100644 src/main/java/org/cryptomator/notify/AppEvent.java create mode 100644 src/main/java/org/cryptomator/notify/Event.java create mode 100644 src/main/java/org/cryptomator/notify/NotificationHandler.java create mode 100644 src/main/java/org/cryptomator/notify/VaultEvent.java create mode 100644 src/main/java/org/cryptomator/ui/eventviewer/EventViewerComponent.java 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 {} From 76a4ef50cb593ef9fed8dc981e6804ed3e58dda1 Mon Sep 17 00:00:00 2001 From: Jan-Peter Klein Date: Tue, 11 Feb 2025 16:21:53 +0100 Subject: [PATCH 012/120] improve exception handling --- .../common/vaults/VaultListManager.java | 30 +++++++++---------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/src/main/java/org/cryptomator/common/vaults/VaultListManager.java b/src/main/java/org/cryptomator/common/vaults/VaultListManager.java index 2e9173a22..c8c37893e 100644 --- a/src/main/java/org/cryptomator/common/vaults/VaultListManager.java +++ b/src/main/java/org/cryptomator/common/vaults/VaultListManager.java @@ -50,9 +50,9 @@ public class VaultListManager { @Inject public VaultListManager(ObservableList vaultList, // AutoLocker autoLocker, // - List mountServices, - VaultComponent.Factory vaultComponentFactory, - ResourceBundle resourceBundle, + List mountServices, // + VaultComponent.Factory vaultComponentFactory, // + ResourceBundle resourceBundle, // Settings settings) { this.vaultList = vaultList; this.autoLocker = autoLocker; @@ -71,17 +71,15 @@ public class VaultListManager { throw new NoSuchFileException(normalizedPathToVault.toString(), null, "Not a vault directory"); } - return get(normalizedPathToVault) // - .orElseGet(() -> { - Vault newVault = create(newVaultSettings(normalizedPathToVault)); - try { - setVaultScheme(newVault); - } catch (IOException e) { - throw new RuntimeException(e); - } - vaultList.add(newVault); - return newVault; - }); + var maybeVault = get(normalizedPathToVault); + if (maybeVault.isEmpty()) { + Vault newVault = create(newVaultSettings(normalizedPathToVault)); + setVaultScheme(newVault); + vaultList.add(newVault); + return newVault; + } else { + return maybeVault.get(); + } } private void setVaultScheme(Vault vault) throws IOException { @@ -94,11 +92,11 @@ public class VaultListManager { } } catch (NoSuchFileException e) { vault.stateProperty().set(VaultState.Value.ERROR); - LOG.error("Configuration file missing or corrupted.", e); + LOG.error("Configuration file missing.", e); } catch (IOException e) { vault.stateProperty().set(VaultState.Value.ERROR); LOG.error("Unexpected IO exception while setting vault scheme.", e); - throw new IOException("Configuration file missing or corrupted.", e); + throw e; } } From 44fe4a6f8ad422521f277d8ff241b9e022fadcc1 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Tue, 11 Feb 2025 17:37:04 +0100 Subject: [PATCH 013/120] displayable event view window --- .../org/cryptomator/ui/common/FxmlFile.java | 1 + .../ui/controls/FontAwesome5Icon.java | 1 + .../ui/eventviewer/EventViewController.java | 14 +++++ .../ui/eventviewer/EventViewerComponent.java | 34 ++++++++++- .../ui/eventviewer/EventViewerModule.java | 57 +++++++++++++++++++ .../ui/eventviewer/EventViewerScoped.java | 13 +++++ .../ui/eventviewer/EventViewerWindow.java | 14 +++++ .../ui/fxapp/FxApplicationModule.java | 4 +- .../ui/fxapp/FxApplicationWindows.java | 10 ++++ .../ui/mainwindow/VaultListController.java | 4 ++ src/main/resources/fxml/eventviewer.fxml | 32 +++++++++++ src/main/resources/fxml/vault_list.fxml | 5 ++ 12 files changed, 187 insertions(+), 2 deletions(-) create mode 100644 src/main/java/org/cryptomator/ui/eventviewer/EventViewController.java create mode 100644 src/main/java/org/cryptomator/ui/eventviewer/EventViewerModule.java create mode 100644 src/main/java/org/cryptomator/ui/eventviewer/EventViewerScoped.java create mode 100644 src/main/java/org/cryptomator/ui/eventviewer/EventViewerWindow.java create mode 100644 src/main/resources/fxml/eventviewer.fxml diff --git a/src/main/java/org/cryptomator/ui/common/FxmlFile.java b/src/main/java/org/cryptomator/ui/common/FxmlFile.java index 6bf8ac7db..a45e21307 100644 --- a/src/main/java/org/cryptomator/ui/common/FxmlFile.java +++ b/src/main/java/org/cryptomator/ui/common/FxmlFile.java @@ -13,6 +13,7 @@ public enum FxmlFile { CONVERTVAULT_HUBTOPASSWORD_CONVERT("/fxml/convertvault_hubtopassword_convert.fxml"), // CONVERTVAULT_HUBTOPASSWORD_SUCCESS("/fxml/convertvault_hubtopassword_success.fxml"), // ERROR("/fxml/error.fxml"), // + EVENT_VIEWER("/fxml/eventviewer.fxml"), // FORGET_PASSWORD("/fxml/forget_password.fxml"), // HEALTH_START("/fxml/health_start.fxml"), // HEALTH_CHECK_LIST("/fxml/health_check_list.fxml"), // diff --git a/src/main/java/org/cryptomator/ui/controls/FontAwesome5Icon.java b/src/main/java/org/cryptomator/ui/controls/FontAwesome5Icon.java index 485e89304..b5a736da8 100644 --- a/src/main/java/org/cryptomator/ui/controls/FontAwesome5Icon.java +++ b/src/main/java/org/cryptomator/ui/controls/FontAwesome5Icon.java @@ -7,6 +7,7 @@ public enum FontAwesome5Icon { ANCHOR("\uF13D"), // ARROW_UP("\uF062"), // BAN("\uF05E"), // + BELL("\uF0F3"), // BUG("\uF188"), // CARET_DOWN("\uF0D7"), // CARET_RIGHT("\uF0Da"), // diff --git a/src/main/java/org/cryptomator/ui/eventviewer/EventViewController.java b/src/main/java/org/cryptomator/ui/eventviewer/EventViewController.java new file mode 100644 index 000000000..2a0921921 --- /dev/null +++ b/src/main/java/org/cryptomator/ui/eventviewer/EventViewController.java @@ -0,0 +1,14 @@ +package org.cryptomator.ui.eventviewer; + +import org.cryptomator.ui.common.FxController; + +import javax.inject.Inject; + +@EventViewerScoped +public class EventViewController implements FxController { + + @Inject + public EventViewController() { + + } +} diff --git a/src/main/java/org/cryptomator/ui/eventviewer/EventViewerComponent.java b/src/main/java/org/cryptomator/ui/eventviewer/EventViewerComponent.java index 8ac56320b..2aa788e21 100644 --- a/src/main/java/org/cryptomator/ui/eventviewer/EventViewerComponent.java +++ b/src/main/java/org/cryptomator/ui/eventviewer/EventViewerComponent.java @@ -1,3 +1,35 @@ package org.cryptomator.ui.eventviewer; -public interface EventViewerComponent {} +import dagger.BindsInstance; +import dagger.Lazy; +import dagger.Subcomponent; +import org.cryptomator.ui.common.FxmlFile; +import org.cryptomator.ui.common.FxmlScene; + +import javax.inject.Named; +import javafx.scene.Scene; +import javafx.stage.Stage; + +@EventViewerScoped +@Subcomponent(modules = {EventViewerModule.class}) +public interface EventViewerComponent { + + @EventViewerWindow + Stage window(); + + @FxmlScene(FxmlFile.EVENT_VIEWER) + Lazy scene(); + + default void showEventViewerWindow() { + Stage stage = window(); + stage.setScene(scene().get()); + stage.sizeToScene(); + stage.show(); + } + + @Subcomponent.Factory + interface Factory { + + EventViewerComponent create(@BindsInstance @Named("owner") Stage owner); + } +} diff --git a/src/main/java/org/cryptomator/ui/eventviewer/EventViewerModule.java b/src/main/java/org/cryptomator/ui/eventviewer/EventViewerModule.java new file mode 100644 index 000000000..1b552f41a --- /dev/null +++ b/src/main/java/org/cryptomator/ui/eventviewer/EventViewerModule.java @@ -0,0 +1,57 @@ +package org.cryptomator.ui.eventviewer; + +import dagger.Binds; +import dagger.Module; +import dagger.Provides; +import dagger.multibindings.IntoMap; +import org.cryptomator.ui.common.DefaultSceneFactory; +import org.cryptomator.ui.common.FxController; +import org.cryptomator.ui.common.FxControllerKey; +import org.cryptomator.ui.common.FxmlFile; +import org.cryptomator.ui.common.FxmlLoaderFactory; +import org.cryptomator.ui.common.FxmlScene; +import org.cryptomator.ui.common.StageFactory; + +import javax.inject.Named; +import javax.inject.Provider; +import javafx.scene.Scene; +import javafx.stage.Modality; +import javafx.stage.Stage; +import java.util.Map; +import java.util.ResourceBundle; + +@Module +abstract class EventViewerModule { + + @Provides + @EventViewerScoped + @EventViewerWindow + static Stage provideStage(StageFactory factory, ResourceBundle resourceBundle, @Named("owner") Stage owner) { + Stage stage = factory.create(); + stage.setTitle("TODO EVENTVIEWER"); + stage.setResizable(true); + stage.initModality(Modality.WINDOW_MODAL); //TODO: or not modal at all? + stage.initOwner(owner); + return stage; + } + + @Provides + @EventViewerScoped + @EventViewerWindow + static FxmlLoaderFactory provideFxmlLoaderFactory(Map, Provider> factories, DefaultSceneFactory sceneFactory, ResourceBundle resourceBundle) { + return new FxmlLoaderFactory(factories, sceneFactory, resourceBundle); + } + + @Binds + @IntoMap + @FxControllerKey(EventViewController.class) + abstract FxController bindEventViewController(EventViewController controller); + + @Provides + @FxmlScene(FxmlFile.EVENT_VIEWER) + @EventViewerScoped + static Scene provideEventViewerScene(@EventViewerWindow FxmlLoaderFactory fxmlLoaders) { + return fxmlLoaders.createScene(FxmlFile.EVENT_VIEWER); + } + +} diff --git a/src/main/java/org/cryptomator/ui/eventviewer/EventViewerScoped.java b/src/main/java/org/cryptomator/ui/eventviewer/EventViewerScoped.java new file mode 100644 index 000000000..24570752a --- /dev/null +++ b/src/main/java/org/cryptomator/ui/eventviewer/EventViewerScoped.java @@ -0,0 +1,13 @@ +package org.cryptomator.ui.eventviewer; + +import javax.inject.Scope; +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Scope +@Documented +@Retention(RetentionPolicy.RUNTIME) +@interface EventViewerScoped { + +} diff --git a/src/main/java/org/cryptomator/ui/eventviewer/EventViewerWindow.java b/src/main/java/org/cryptomator/ui/eventviewer/EventViewerWindow.java new file mode 100644 index 000000000..eb67184bd --- /dev/null +++ b/src/main/java/org/cryptomator/ui/eventviewer/EventViewerWindow.java @@ -0,0 +1,14 @@ +package org.cryptomator.ui.eventviewer; + +import javax.inject.Qualifier; +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; + +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +@Qualifier +@Documented +@Retention(RUNTIME) +@interface EventViewerWindow { + +} diff --git a/src/main/java/org/cryptomator/ui/fxapp/FxApplicationModule.java b/src/main/java/org/cryptomator/ui/fxapp/FxApplicationModule.java index af98e284c..37fb3e0f3 100644 --- a/src/main/java/org/cryptomator/ui/fxapp/FxApplicationModule.java +++ b/src/main/java/org/cryptomator/ui/fxapp/FxApplicationModule.java @@ -8,6 +8,7 @@ package org.cryptomator.ui.fxapp; import dagger.Module; import dagger.Provides; import org.cryptomator.ui.error.ErrorComponent; +import org.cryptomator.ui.eventviewer.EventViewerComponent; import org.cryptomator.ui.health.HealthCheckComponent; import org.cryptomator.ui.lock.LockComponent; import org.cryptomator.ui.mainwindow.MainWindowComponent; @@ -33,7 +34,8 @@ import java.io.InputStream; ErrorComponent.class, // HealthCheckComponent.class, // UpdateReminderComponent.class, // - ShareVaultComponent.class}) + ShareVaultComponent.class, // + EventViewerComponent.class}) abstract class FxApplicationModule { private static Image createImageFromResource(String resourceName) throws IOException { diff --git a/src/main/java/org/cryptomator/ui/fxapp/FxApplicationWindows.java b/src/main/java/org/cryptomator/ui/fxapp/FxApplicationWindows.java index 54acf62a3..b5d2a1973 100644 --- a/src/main/java/org/cryptomator/ui/fxapp/FxApplicationWindows.java +++ b/src/main/java/org/cryptomator/ui/fxapp/FxApplicationWindows.java @@ -7,6 +7,7 @@ import org.cryptomator.common.vaults.VaultState; import org.cryptomator.integrations.tray.TrayIntegrationProvider; import org.cryptomator.ui.dialogs.Dialogs; import org.cryptomator.ui.error.ErrorComponent; +import org.cryptomator.ui.eventviewer.EventViewerComponent; import org.cryptomator.ui.lock.LockComponent; import org.cryptomator.ui.mainwindow.MainWindowComponent; import org.cryptomator.ui.preferences.PreferencesComponent; @@ -51,6 +52,7 @@ public class FxApplicationWindows { private final UpdateReminderComponent.Factory updateReminderWindowFactory; private final LockComponent.Factory lockWorkflowFactory; private final ErrorComponent.Factory errorWindowFactory; + private final EventViewerComponent.Factory eventViewWindow; private final ExecutorService executor; private final VaultOptionsComponent.Factory vaultOptionsWindow; private final ShareVaultComponent.Factory shareVaultWindow; @@ -69,6 +71,7 @@ public class FxApplicationWindows { ErrorComponent.Factory errorWindowFactory, // VaultOptionsComponent.Factory vaultOptionsWindow, // ShareVaultComponent.Factory shareVaultWindow, // + EventViewerComponent.Factory eventViewWindow, // ExecutorService executor, // Dialogs dialogs) { this.primaryStage = primaryStage; @@ -80,6 +83,7 @@ public class FxApplicationWindows { this.updateReminderWindowFactory = updateReminderWindowFactory; this.lockWorkflowFactory = lockWorkflowFactory; this.errorWindowFactory = errorWindowFactory; + this.eventViewWindow = eventViewWindow; this.executor = executor; this.vaultOptionsWindow = vaultOptionsWindow; this.shareVaultWindow = shareVaultWindow; @@ -200,4 +204,10 @@ public class FxApplicationWindows { } } + public CompletionStage showEventViewer(@Nullable Stage owner) { + return CompletableFuture.supplyAsync(() -> { + eventViewWindow.create(owner).showEventViewerWindow(); + return null; + }, Platform::runLater); + } } diff --git a/src/main/java/org/cryptomator/ui/mainwindow/VaultListController.java b/src/main/java/org/cryptomator/ui/mainwindow/VaultListController.java index 0c2c46204..8af7befe1 100644 --- a/src/main/java/org/cryptomator/ui/mainwindow/VaultListController.java +++ b/src/main/java/org/cryptomator/ui/mainwindow/VaultListController.java @@ -264,6 +264,10 @@ public class VaultListController implements FxController { appWindows.showPreferencesWindow(SelectedPreferencesTab.ANY); } + @FXML + public void showEventViewer() { + appWindows.showEventViewer(mainWindow); + } // Getter and Setter public BooleanBinding emptyVaultListProperty() { diff --git a/src/main/resources/fxml/eventviewer.fxml b/src/main/resources/fxml/eventviewer.fxml new file mode 100644 index 000000000..fa268bb45 --- /dev/null +++ b/src/main/resources/fxml/eventviewer.fxml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/fxml/vault_list.fxml b/src/main/resources/fxml/vault_list.fxml index 161a29e87..2a82a514f 100644 --- a/src/main/resources/fxml/vault_list.fxml +++ b/src/main/resources/fxml/vault_list.fxml @@ -42,6 +42,11 @@ +