diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml index a82e89ba7..abb1b4a92 100644 --- a/.github/ISSUE_TEMPLATE/bug.yml +++ b/.github/ISSUE_TEMPLATE/bug.yml @@ -1,7 +1,14 @@ name: Bug Report description: Create a report to help us improve -labels: ["type:bug"] +type: "Bug" body: + - type: input + id: summary + attributes: + label: Summary + placeholder: Please summarize your problem. + validations: + required: true - type: checkboxes id: terms attributes: @@ -11,13 +18,6 @@ body: required: true - label: I agree to follow this project's [Code of Conduct](https://github.com/cryptomator/cryptomator/blob/develop/.github/CODE_OF_CONDUCT.md) required: true - - type: input - id: summary - attributes: - label: Summary - placeholder: Please summarize your problem. - validations: - required: true - type: textarea id: software-versions attributes: @@ -97,4 +97,4 @@ body: id: further-info attributes: label: Anything else? - description: Links? References? Screenshots? Configurations? Any data that might be necessary to reproduce the issue? + description: Links? References? Screenshots? Configurations? Any data that might be necessary to reproduce the issue? \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/feature.yml b/.github/ISSUE_TEMPLATE/feature.yml index 652f27234..826f3410a 100644 --- a/.github/ISSUE_TEMPLATE/feature.yml +++ b/.github/ISSUE_TEMPLATE/feature.yml @@ -1,7 +1,14 @@ name: Feature Request description: Suggest an idea for this project -labels: ["type:feature-request"] +type: "Feature" body: + - type: input + id: summary + attributes: + label: Summary + placeholder: Please summarize your feature request. + validations: + required: true - type: checkboxes id: terms attributes: @@ -11,13 +18,6 @@ body: required: true - label: I agree to follow this project's [Code of Conduct](https://github.com/cryptomator/cryptomator/blob/develop/.github/CODE_OF_CONDUCT.md) required: true - - type: input - id: summary - attributes: - label: Summary - placeholder: Please summarize your feature request. - validations: - required: true - type: textarea id: motivation attributes: diff --git a/.github/workflows/debian.yml b/.github/workflows/debian.yml index 16c5bc530..fa021d441 100644 --- a/.github/workflows/debian.yml +++ b/.github/workflows/debian.yml @@ -28,7 +28,7 @@ env: jobs: build: name: Build Debian Package - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 - id: versions diff --git a/dist/linux/common/org.cryptomator.Cryptomator.metainfo.xml b/dist/linux/common/org.cryptomator.Cryptomator.metainfo.xml index c91a3db6e..d69716e06 100644 --- a/dist/linux/common/org.cryptomator.Cryptomator.metainfo.xml +++ b/dist/linux/common/org.cryptomator.Cryptomator.metainfo.xml @@ -6,6 +6,12 @@ Cryptomator Encryption for your cloud made easy + + encryption + security + privacy + +

Cryptomator provides easy-to-use, transparent, client-side encryption for your cloud. @@ -43,16 +49,16 @@ - Encrypt your data, protect your privacy - https://static.cryptomator.org/desktop/flathubScreenshots/MainWindowUnlocked_light.png + Encrypts your data, protects your privacy + https://static.cryptomator.org/desktop/flathubScreenshots/MainWindowUnlockDialog_light.png Dark theme available https://static.cryptomator.org/desktop/flathubScreenshots/MainWindowUnlocked_dark.png - Uses AES-GCM 256 - an industry standardized, quantum resistant encryption - https://static.cryptomator.org/desktop/flathubScreenshots/MainWindowUnlockDialog_light.png + Easy to use - work on encrypted files as if they were not + https://static.cryptomator.org/desktop/flathubScreenshots/MainWindowUnlocked_light.png diff --git a/src/main/java/org/cryptomator/common/settings/VaultSettings.java b/src/main/java/org/cryptomator/common/settings/VaultSettings.java index fd21fc197..5112415b4 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 lastKnownKeyLoader; 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.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; @@ -99,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, lastKnownKeyLoader}; } public static VaultSettings withRandomId() { @@ -130,6 +132,7 @@ public class VaultSettings { json.mountPoint = mountPoint.map(Path::toString).getValue(); json.mountService = mountService.get(); json.port = port.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 43aa204e8..870b74e07 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("lastKnownKeyLoader") + String lastKnownKeyLoader; + @JsonProperty("port") int port = VaultSettings.DEFAULT_PORT; diff --git a/src/main/java/org/cryptomator/common/vaults/VaultListManager.java b/src/main/java/org/cryptomator/common/vaults/VaultListManager.java index 87faff77a..c362ca0c0 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; @@ -49,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; @@ -114,6 +115,10 @@ public class VaultListManager { private Vault create(VaultSettings vaultSettings) { var wrapper = new VaultConfigCache(vaultSettings); try { + if (Objects.isNull(vaultSettings.lastKnownKeyLoader.get())) { + var keyIdScheme = wrapper.get().getKeyId().getScheme(); + vaultSettings.lastKnownKeyLoader.set(keyIdScheme); + } var vaultState = determineVaultState(vaultSettings.path.get()); if (vaultState == LOCKED) { //for legacy reasons: pre v8 vault do not have a config, but they are in the NEEDS_MIGRATION state wrapper.reloadConfig(); diff --git a/src/main/java/org/cryptomator/ui/addvaultwizard/ReadmeGenerator.java b/src/main/java/org/cryptomator/ui/addvaultwizard/ReadmeGenerator.java index 2ffda4d73..a25384c78 100644 --- a/src/main/java/org/cryptomator/ui/addvaultwizard/ReadmeGenerator.java +++ b/src/main/java/org/cryptomator/ui/addvaultwizard/ReadmeGenerator.java @@ -76,8 +76,10 @@ public class ReadmeGenerator { input.chars().forEachOrdered(c -> { if (c < 128) { sb.append((char) c); + } else if (c <= 0xFF) { + sb.append("\\'").append(String.format("%02X", c)); } else if (c < 0xFFFF) { - sb.append("\\u").append(c); + sb.append("\\uc1\\u").append(c); } }); } diff --git a/src/main/java/org/cryptomator/ui/convertvault/HubToPasswordConvertController.java b/src/main/java/org/cryptomator/ui/convertvault/HubToPasswordConvertController.java index fd6d49b89..dc95f7051 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().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/dialogs/Dialogs.java b/src/main/java/org/cryptomator/ui/dialogs/Dialogs.java index 5107fe740..837bea012 100644 --- a/src/main/java/org/cryptomator/ui/dialogs/Dialogs.java +++ b/src/main/java/org/cryptomator/ui/dialogs/Dialogs.java @@ -38,7 +38,7 @@ public class Dialogs { .setMessageKey("removeVault.message") // .setDescriptionKey("removeVault.description") // .setIcon(FontAwesome5Icon.QUESTION) // - .setOkButtonKey("removeVault.confirmBtn") // + .setOkButtonKey("generic.button.remove") // .setCancelButtonKey("generic.button.cancel") // .setOkAction(stage -> { LOG.debug("Removing vault {}.", vault.getDisplayName()); @@ -54,7 +54,7 @@ public class Dialogs { .setMessageKey("removeCert.message") // .setDescriptionKey("removeCert.description") // .setIcon(FontAwesome5Icon.QUESTION) // - .setOkButtonKey("removeCert.confirmBtn") // + .setOkButtonKey("generic.button.remove") // .setCancelButtonKey("generic.button.cancel") // .setOkAction(stage -> { settings.licenseKey.set(null); diff --git a/src/main/java/org/cryptomator/ui/dialogs/SimpleDialog.java b/src/main/java/org/cryptomator/ui/dialogs/SimpleDialog.java index 84d9e4f75..08f77849e 100644 --- a/src/main/java/org/cryptomator/ui/dialogs/SimpleDialog.java +++ b/src/main/java/org/cryptomator/ui/dialogs/SimpleDialog.java @@ -31,8 +31,9 @@ public class SimpleDialog { FxmlLoaderFactory loaderFactory = FxmlLoaderFactory.forController( // new SimpleDialogController(resolveText(builder.messageKey, null), // resolveText(builder.descriptionKey, null), // - builder.icon, resolveText(builder.okButtonKey, null), // - resolveText(builder.cancelButtonKey, null), // + builder.icon, // + resolveText(builder.okButtonKey, null), // + builder.cancelButtonKey != null ? resolveText(builder.cancelButtonKey, null) : null, // () -> builder.okAction.accept(dialogStage), // () -> builder.cancelAction.accept(dialogStage)), // Scene::new, builder.resourceBundle); @@ -67,7 +68,6 @@ public class SimpleDialog { private String descriptionKey; private String okButtonKey; private String cancelButtonKey; - private FontAwesome5Icon icon; private Consumer okAction = Stage::close; private Consumer cancelAction = Stage::close; @@ -128,7 +128,6 @@ public class SimpleDialog { Objects.requireNonNull(messageKey, "SimpleDialog messageKey must be set."); Objects.requireNonNull(descriptionKey, "SimpleDialog descriptionKey must be set."); Objects.requireNonNull(okButtonKey, "SimpleDialog okButtonKey must be set."); - Objects.requireNonNull(cancelButtonKey, "SimpleDialog cancelButtonKey must be set."); try { return new SimpleDialog(this); diff --git a/src/main/java/org/cryptomator/ui/dialogs/SimpleDialogController.java b/src/main/java/org/cryptomator/ui/dialogs/SimpleDialogController.java index 0eee1b308..bbf590145 100644 --- a/src/main/java/org/cryptomator/ui/dialogs/SimpleDialogController.java +++ b/src/main/java/org/cryptomator/ui/dialogs/SimpleDialogController.java @@ -14,6 +14,7 @@ public class SimpleDialogController implements FxController { private final String cancelButtonText; private final Runnable okAction; private final Runnable cancelAction; + private final boolean cancelButtonVisible; public SimpleDialogController(String message, String description, FontAwesome5Icon icon, String okButtonText, String cancelButtonText, Runnable okAction, Runnable cancelAction) { this.message = message; @@ -23,6 +24,11 @@ public class SimpleDialogController implements FxController { this.cancelButtonText = cancelButtonText; this.okAction = okAction; this.cancelAction = cancelAction; + this.cancelButtonVisible = cancelButtonText != null && !cancelButtonText.isEmpty(); + } + + public boolean isCancelButtonVisible() { + return cancelButtonVisible; } public String getMessage() { diff --git a/src/main/java/org/cryptomator/ui/keyloading/KeyLoadingStrategy.java b/src/main/java/org/cryptomator/ui/keyloading/KeyLoadingStrategy.java index f3f0aff8e..b9af0f4a3 100644 --- a/src/main/java/org/cryptomator/ui/keyloading/KeyLoadingStrategy.java +++ b/src/main/java/org/cryptomator/ui/keyloading/KeyLoadingStrategy.java @@ -3,6 +3,8 @@ 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.cryptomator.ui.keyloading.masterkeyfile.MasterkeyFileLoadingStrategy; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -28,6 +30,33 @@ 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 HubKeyLoadingStrategy.SCHEME_HUB_HTTP.equals(keyLoader) || HubKeyLoadingStrategy.SCHEME_HUB_HTTPS.equals(keyLoader); + } + + /** + * Determines whether the provided key loader scheme corresponds to a Masterkey File Vault. + *

+ * This method checks if the {@code keyLoader} parameter matches the known Masterkey File Vault scheme + * {@link MasterkeyFileLoadingStrategy#SCHEME}. + *

+ * + * @param keyLoader A string representing the key loader scheme to be checked. + * @return {@code true} if the given key loader scheme represents a Masterkey File Vault; {@code false} otherwise. + */ + static boolean isMasterkeyFileVault(String keyLoader) { + return MasterkeyFileLoadingStrategy.SCHEME.equals(keyLoader); + } + /** * Allows the loader to try and recover from an exception thrown during the last attempt. * diff --git a/src/main/java/org/cryptomator/ui/keyloading/hub/ReceiveKeyController.java b/src/main/java/org/cryptomator/ui/keyloading/hub/ReceiveKeyController.java index aa56a22e7..f94d882fa 100644 --- a/src/main/java/org/cryptomator/ui/keyloading/hub/ReceiveKeyController.java +++ b/src/main/java/org/cryptomator/ui/keyloading/hub/ReceiveKeyController.java @@ -165,6 +165,7 @@ public class ReceiveKeyController implements FxController { var vaultKeyUri = hubConfig.URIs.API.resolve("vaults/" + vaultId + "/access-token"); var request = HttpRequest.newBuilder(vaultKeyUri) // .header("Authorization", "Bearer " + bearerToken) // + .header("Hub-Device-ID", deviceId) // .GET() // .timeout(REQ_TIMEOUT) // .build(); diff --git a/src/main/java/org/cryptomator/ui/mainwindow/MainWindowController.java b/src/main/java/org/cryptomator/ui/mainwindow/MainWindowController.java index 13412dd27..18db5e5ac 100644 --- a/src/main/java/org/cryptomator/ui/mainwindow/MainWindowController.java +++ b/src/main/java/org/cryptomator/ui/mainwindow/MainWindowController.java @@ -19,9 +19,11 @@ import javafx.beans.property.ObjectProperty; import javafx.beans.property.ReadOnlyBooleanProperty; import javafx.beans.property.ReadOnlyObjectProperty; import javafx.fxml.FXML; +import javafx.geometry.Rectangle2D; import javafx.scene.layout.StackPane; import javafx.stage.Screen; import javafx.stage.Stage; +import javafx.stage.WindowEvent; @MainWindowScoped public class MainWindowController implements FxController { @@ -68,18 +70,15 @@ public class MainWindowController implements FxController { 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 + if (windowPositionSaved(x, y, width, height)) { + window.setX(x); + window.setY(y); + window.setWidth(Math.clamp(width, window.getMinWidth(), window.getMaxWidth())); + window.setHeight(Math.clamp(height, window.getMinHeight(), window.getMaxHeight())); } + window.setOnShowing(this::checkDisplayBounds); + settings.windowXPosition.bind(window.xProperty()); settings.windowYPosition.bind(window.yProperty()); settings.windowWidth.bind(window.widthProperty()); @@ -90,6 +89,39 @@ public class MainWindowController implements FxController { return x != 0 || y != 0 || width != 0 || height != 0; } + private void checkDisplayBounds(WindowEvent windowEvent) { + int x = settings.windowXPosition.get(); + int y = settings.windowYPosition.get(); + int width = settings.windowWidth.get(); + int height = settings.windowHeight.get(); + + // Minimizing a window in Windows and closing it could result in an out of bounds position at (x, y) = (-32000, -32000) + // See https://devblogs.microsoft.com/oldnewthing/20041028-00/?p=37453 + // If the position is (-32000, -32000), restore to the last saved position + if (window.getX() == -32000 && window.getY() == -32000) { + window.setX(x); + window.setY(y); + window.setWidth(width); + window.setHeight(height); + } + + Rectangle2D primaryScreenBounds = Screen.getPrimary().getBounds(); + if (!isWithinDisplayBounds(x, y, width, height)) { //use stored window position + LOG.debug("Resetting window position due to insufficient screen overlap"); + var centeredX = (primaryScreenBounds.getWidth() - window.getMinWidth()) / 2; + var centeredY = (primaryScreenBounds.getHeight() - window.getMinHeight()) / 2; + //check if we can keep width and height + if (isWithinDisplayBounds((int) centeredX, (int) centeredY, width, height)) { + //if so, keep window size + window.setWidth(Math.clamp(width, window.getMinWidth(), window.getMaxWidth())); + window.setHeight(Math.clamp(height, window.getMinHeight(), window.getMaxHeight())); + } + //reset position of upper left corner + window.setX(centeredX); + window.setY(centeredY); + } + } + 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 diff --git a/src/main/java/org/cryptomator/ui/sharevault/ShareVaultController.java b/src/main/java/org/cryptomator/ui/sharevault/ShareVaultController.java index 63230cbbf..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 vaultScheme = vault.getVaultConfigCache().getUnchecked().getKeyId().getScheme(); - this.hubVault = (vaultScheme.equals(HubKeyLoadingStrategy.SCHEME_HUB_HTTP) || vaultScheme.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 78d228995..154eb30dd 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; @@ -42,11 +43,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().lastKnownKeyLoader.get(); + if(!KeyLoadingStrategy.isMasterkeyFileVault(vaultKeyLoader)){ tabPane.getTabs().remove(keyTab); } - if(!(vaultScheme.equals(HubKeyLoadingStrategy.SCHEME_HUB_HTTP) || vaultScheme.equals(HubKeyLoadingStrategy.SCHEME_HUB_HTTPS))){ + if(!KeyLoadingStrategy.isHubVault(vaultKeyLoader)){ tabPane.getTabs().remove(hubTab); } diff --git a/src/main/resources/css/dark_theme.css b/src/main/resources/css/dark_theme.css index abb6efe57..4d3db3968 100644 --- a/src/main/resources/css/dark_theme.css +++ b/src/main/resources/css/dark_theme.css @@ -359,6 +359,12 @@ -fx-background-color: PRIMARY; } +.notification-debug:hover .notification-label, +.notification-update:hover .notification-label, +.notification-support:hover .notification-label { + -fx-underline:true; +} + /******************************************************************************* * * * ScrollBar * diff --git a/src/main/resources/css/light_theme.css b/src/main/resources/css/light_theme.css index b4376eaf5..dec0a33de 100644 --- a/src/main/resources/css/light_theme.css +++ b/src/main/resources/css/light_theme.css @@ -397,6 +397,12 @@ -fx-background-color: PRIMARY; } +.notification-debug:hover .notification-label, +.notification-update:hover .notification-label, +.notification-support:hover .notification-label { + -fx-underline:true; +} + /******************************************************************************* * * * ScrollBar * diff --git a/src/main/resources/fxml/simple_dialog.fxml b/src/main/resources/fxml/simple_dialog.fxml index 32ad63abf..0e9b01776 100644 --- a/src/main/resources/fxml/simple_dialog.fxml +++ b/src/main/resources/fxml/simple_dialog.fxml @@ -1,16 +1,16 @@ - - - - - - - - - + + + + + + + + + -