diff --git a/README.md b/README.md index 6f0e316f4..5b252fc35 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![Build](https://github.com/cryptomator/cryptomator/workflows/Build/badge.svg)](https://github.com/cryptomator/cryptomator/actions?query=workflow%3ABuild) [![Known Vulnerabilities](https://snyk.io/test/github/cryptomator/cryptomator/badge.svg)](https://snyk.io/test/github/cryptomator/cryptomator) [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=cryptomator_cryptomator&metric=alert_status)](https://sonarcloud.io/dashboard?id=cryptomator_cryptomator) -[![Twitter](https://img.shields.io/badge/twitter-@Cryptomator-blue.svg?style=flat)](http://twitter.com/Cryptomator) +[![Mastodon](https://img.shields.io/mastodon/follow/176112?domain=mastodon.online&style=flat)](https://mastodon.online/@cryptomator) [![Crowdin](https://badges.crowdin.net/cryptomator/localized.svg)](https://translate.cryptomator.org/) [![Latest Release](https://img.shields.io/github/release/cryptomator/cryptomator.svg)](https://github.com/cryptomator/cryptomator/releases/latest) [![Community](https://img.shields.io/badge/help-Community-orange.svg)](https://community.cryptomator.org) diff --git a/src/main/java/org/cryptomator/ui/dialogs/Dialogs.java b/src/main/java/org/cryptomator/ui/dialogs/Dialogs.java index b6066b655..5107fe740 100644 --- a/src/main/java/org/cryptomator/ui/dialogs/Dialogs.java +++ b/src/main/java/org/cryptomator/ui/dialogs/Dialogs.java @@ -2,31 +2,34 @@ package org.cryptomator.ui.dialogs; import org.cryptomator.common.settings.Settings; import org.cryptomator.common.vaults.Vault; +import org.cryptomator.ui.common.StageFactory; import org.cryptomator.ui.controls.FontAwesome5Icon; +import org.cryptomator.ui.fxapp.FxApplicationScoped; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.inject.Inject; -import javax.inject.Singleton; import javafx.collections.ObservableList; import javafx.stage.Stage; import java.util.ResourceBundle; import java.util.function.Consumer; -@Singleton +@FxApplicationScoped public class Dialogs { private final ResourceBundle resourceBundle; + private final StageFactory stageFactory; @Inject - public Dialogs(ResourceBundle resourceBundle) { + public Dialogs(ResourceBundle resourceBundle, StageFactory stageFactory) { this.resourceBundle = resourceBundle; + this.stageFactory = stageFactory; } private static final Logger LOG = LoggerFactory.getLogger(Dialogs.class); private SimpleDialog.Builder createDialogBuilder() { - return new SimpleDialog.Builder(resourceBundle); + return new SimpleDialog.Builder(resourceBundle, stageFactory); } public SimpleDialog.Builder prepareRemoveVaultDialog(Stage window, Vault vault, ObservableList vaults) { diff --git a/src/main/java/org/cryptomator/ui/dialogs/SimpleDialog.java b/src/main/java/org/cryptomator/ui/dialogs/SimpleDialog.java index d2d60d297..84d9e4f75 100644 --- a/src/main/java/org/cryptomator/ui/dialogs/SimpleDialog.java +++ b/src/main/java/org/cryptomator/ui/dialogs/SimpleDialog.java @@ -2,6 +2,7 @@ package org.cryptomator.ui.dialogs; import org.cryptomator.ui.common.FxmlFile; import org.cryptomator.ui.common.FxmlLoaderFactory; +import org.cryptomator.ui.common.StageFactory; import org.cryptomator.ui.controls.FontAwesome5Icon; import javafx.scene.Scene; @@ -17,24 +18,23 @@ import java.util.function.Consumer; public class SimpleDialog { private final ResourceBundle resourceBundle; - private final Stage dialogStage; SimpleDialog(Builder builder) throws IOException { this.resourceBundle = builder.resourceBundle; - dialogStage = new Stage(); + dialogStage = builder.stageFactory.create(); dialogStage.initOwner(builder.owner); dialogStage.initModality(Modality.WINDOW_MODAL); dialogStage.setTitle(resolveText(builder.titleKey, builder.titleArgs)); dialogStage.setResizable(false); - 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.okAction.accept(dialogStage), - () -> builder.cancelAction.accept(dialogStage)), + 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.okAction.accept(dialogStage), // + () -> builder.cancelAction.accept(dialogStage)), // Scene::new, builder.resourceBundle); dialogStage.setScene(new Scene(loaderFactory.load(FxmlFile.SIMPLE_DIALOG.getRessourcePathString()).getRoot())); @@ -60,6 +60,7 @@ public class SimpleDialog { private Stage owner; private final ResourceBundle resourceBundle; + private final StageFactory stageFactory; private String titleKey; private String[] titleArgs; private String messageKey; @@ -71,8 +72,9 @@ public class SimpleDialog { private Consumer okAction = Stage::close; private Consumer cancelAction = Stage::close; - public Builder(ResourceBundle resourceBundle) { + public Builder(ResourceBundle resourceBundle, StageFactory stageFactory) { this.resourceBundle = resourceBundle; + this.stageFactory = stageFactory; } public Builder setOwner(Stage owner) { @@ -122,11 +124,11 @@ public class SimpleDialog { } public SimpleDialog build() { - Objects.requireNonNull(titleKey,"SimpleDialog titleKey must be set."); - 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."); + Objects.requireNonNull(titleKey, "SimpleDialog titleKey must be set."); + 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/mainwindow/VaultListCellController.java b/src/main/java/org/cryptomator/ui/mainwindow/VaultListCellController.java index 38d7ed1c7..75ce21dfe 100644 --- a/src/main/java/org/cryptomator/ui/mainwindow/VaultListCellController.java +++ b/src/main/java/org/cryptomator/ui/mainwindow/VaultListCellController.java @@ -13,10 +13,16 @@ import javax.inject.Inject; import javafx.beans.property.ObjectProperty; import javafx.beans.property.SimpleObjectProperty; import javafx.beans.value.ObservableValue; +import javafx.fxml.FXML; +import javafx.geometry.Insets; +import javafx.scene.layout.HBox; // unscoped because each cell needs its own controller public class VaultListCellController implements FxController { + private static final Insets COMPACT_INSETS = new Insets(6, 12, 6, 12); + private static final Insets DEFAULT_INSETS = new Insets(12); + private final ObjectProperty vault = new SimpleObjectProperty<>(); private final ObservableValue glyph; private final ObservableValue compactMode; @@ -25,6 +31,8 @@ public class VaultListCellController implements FxController { /* FXML */ public FontAwesome5IconView vaultStateView; + @FXML + public HBox vaultListCell; @Inject VaultListCellController(Settings settings) { @@ -37,6 +45,7 @@ public class VaultListCellController implements FxController { .onCondition(vault.flatMap(Vault::stateProperty).map(VaultState.Value.PROCESSING::equals).orElse(false)) // .afterStop(() -> vaultStateView.setRotate(0)) // .build(); + this.vaultListCell.paddingProperty().bind(compactMode.map(c -> c ? COMPACT_INSETS : DEFAULT_INSETS)); } // TODO deduplicate w/ VaultDetailController diff --git a/src/main/java/org/cryptomator/ui/vaultoptions/MountOptionsController.java b/src/main/java/org/cryptomator/ui/vaultoptions/MountOptionsController.java index 106623985..a9a2042a3 100644 --- a/src/main/java/org/cryptomator/ui/vaultoptions/MountOptionsController.java +++ b/src/main/java/org/cryptomator/ui/vaultoptions/MountOptionsController.java @@ -17,6 +17,8 @@ import org.cryptomator.ui.preferences.VolumePreferencesController; import javax.inject.Inject; import javafx.application.Application; import javafx.beans.binding.Bindings; +import javafx.beans.binding.BooleanBinding; +import javafx.beans.value.ObservableBooleanValue; import javafx.beans.value.ObservableValue; import javafx.fxml.FXML; import javafx.scene.control.Button; @@ -50,7 +52,6 @@ public class MountOptionsController implements FxController { private final ObservableValue defaultMountFlags; private final ObservableValue mountpointDirSupported; private final ObservableValue mountpointDriveLetterSupported; - private final ObservableValue readOnlySupported; private final ObservableValue mountFlagsSupported; private final ObservableValue defaultMountServiceSelected; private final ObservableValue directoryPath; @@ -60,6 +61,7 @@ public class MountOptionsController implements FxController { private final ObservableValue selectedMountService; private final ObservableValue selectedMountServiceRequiresRestart; private final ObservableValue loopbackPortChangeable; + private final ObservableBooleanValue readOnlyOptionAllowed; //-- FXML objects -- @@ -108,10 +110,10 @@ public class MountOptionsController implements FxController { }); this.mountFlagsSupported = selectedMountService.map(s -> s.hasCapability(MountCapability.MOUNT_FLAGS)); this.defaultMountServiceSelected = ObservableUtil.mapWithDefault(vaultSettings.mountService, _ -> false, true); - this.readOnlySupported = selectedMountService.map(s -> s.hasCapability(MountCapability.READ_ONLY)); this.mountpointDirSupported = selectedMountService.map(s -> s.hasCapability(MountCapability.MOUNT_TO_EXISTING_DIR) || s.hasCapability(MountCapability.MOUNT_WITHIN_EXISTING_PARENT)); this.mountpointDriveLetterSupported = selectedMountService.map(s -> s.hasCapability(MountCapability.MOUNT_AS_DRIVE_LETTER)); this.loopbackPortChangeable = selectedMountService.map(s -> s.hasCapability(MountCapability.LOOPBACK_PORT) && vaultSettings.mountService.getValue() != null); + this.readOnlyOptionAllowed = BooleanBinding.booleanExpression(selectedMountService.map(s -> s.hasCapability(MountCapability.READ_ONLY))).or(vaultSettings.usesReadOnlyMode); } private MountService reselectMountService() { @@ -345,12 +347,12 @@ public class MountOptionsController implements FxController { return mountpointDriveLetterSupported.getValue(); } - public ObservableValue readOnlySupportedProperty() { - return readOnlySupported; + public ObservableValue readOnlyOptionAllowedProperty() { + return readOnlyOptionAllowed; } - public boolean isReadOnlySupported() { - return readOnlySupported.getValue(); + public boolean isReadOnlyOptionAllowed() { + return readOnlyOptionAllowed.getValue(); } public ObservableValue directoryPathProperty() { diff --git a/src/main/resources/fxml/vault_list_cell.fxml b/src/main/resources/fxml/vault_list_cell.fxml index c6cc8cf24..20df9b924 100644 --- a/src/main/resources/fxml/vault_list_cell.fxml +++ b/src/main/resources/fxml/vault_list_cell.fxml @@ -1,22 +1,19 @@ - - - - diff --git a/src/main/resources/fxml/vault_options_mount.fxml b/src/main/resources/fxml/vault_options_mount.fxml index d5df2534f..4f6295af8 100644 --- a/src/main/resources/fxml/vault_options_mount.fxml +++ b/src/main/resources/fxml/vault_options_mount.fxml @@ -54,7 +54,7 @@