diff --git a/.github/workflows/appimage.yml b/.github/workflows/appimage.yml index 44ca02028..d3dcc85f8 100644 --- a/.github/workflows/appimage.yml +++ b/.github/workflows/appimage.yml @@ -85,6 +85,7 @@ jobs: --java-options "-Xmx256m" --java-options "-Dcryptomator.appVersion=\"${{ needs.get-version.outputs.semVerStr }}\"" --java-options "-Dfile.encoding=\"utf-8\"" + --java-options "-Djava.net.useSystemProxies=true" --java-options "-Dcryptomator.logDir=\"@{userhome}/.local/share/Cryptomator/logs\"" --java-options "-Dcryptomator.pluginDir=\"@{userhome}/.local/share/Cryptomator/plugins\"" --java-options "-Dcryptomator.settingsPath=\"@{userhome}/.config/Cryptomator/settings.json:@{userhome}/.Cryptomator/settings.json\"" diff --git a/.github/workflows/mac-dmg.yml b/.github/workflows/mac-dmg.yml index bad7f572c..401f22b87 100644 --- a/.github/workflows/mac-dmg.yml +++ b/.github/workflows/mac-dmg.yml @@ -95,6 +95,7 @@ jobs: --java-options "-Xss5m" --java-options "-Xmx256m" --java-options "-Dfile.encoding=\"utf-8\"" + --java-options "-Djava.net.useSystemProxies=true" --java-options "-Dapple.awt.enableTemplateImages=true" --java-options "-Dsun.java2d.metal=true" --java-options "-Dcryptomator.appVersion=\"${{ needs.get-version.outputs.semVerStr }}\"" diff --git a/.github/workflows/win-exe.yml b/.github/workflows/win-exe.yml index 8a66e524b..6f241c16d 100644 --- a/.github/workflows/win-exe.yml +++ b/.github/workflows/win-exe.yml @@ -112,6 +112,7 @@ jobs: --java-options "-Xmx256m" --java-options "-Dcryptomator.appVersion=\"${{ needs.get-version.outputs.semVerStr }}\"" --java-options "-Dfile.encoding=\"utf-8\"" + --java-options "-Djava.net.useSystemProxies=true" --java-options "-Dcryptomator.logDir=\"@{localappdata}/Cryptomator\"" --java-options "-Dcryptomator.pluginDir=\"@{appdata}/Cryptomator/Plugins\"" --java-options "-Dcryptomator.settingsPath=\"@{appdata}/Cryptomator/settings.json;@{userhome}/AppData/Roaming/Cryptomator/settings.json\"" diff --git a/dist/linux/appimage/build.sh b/dist/linux/appimage/build.sh index aaa28c587..21494a3c8 100755 --- a/dist/linux/appimage/build.sh +++ b/dist/linux/appimage/build.sh @@ -50,6 +50,7 @@ ${JAVA_HOME}/bin/jpackage \ --java-options "-Xmx256m" \ --app-version "${VERSION}.${REVISION_NO}" \ --java-options "-Dfile.encoding=\"utf-8\"" \ + --java-options "-Djava.net.useSystemProxies=true" \ --java-options "-Dcryptomator.logDir=\"@{userhome}/.local/share/Cryptomator/logs\"" \ --java-options "-Dcryptomator.pluginDir=\"@{userhome}/.local/share/Cryptomator/plugins\"" \ --java-options "-Dcryptomator.settingsPath=\"@{userhome}/.config/Cryptomator/settings.json:@{userhome}/.Cryptomator/settings.json\"" \ diff --git a/dist/linux/debian/rules b/dist/linux/debian/rules index e1aec8068..23b0eb2bd 100755 --- a/dist/linux/debian/rules +++ b/dist/linux/debian/rules @@ -48,6 +48,7 @@ override_dh_auto_build: --java-options "-Xss5m" \ --java-options "-Xmx256m" \ --java-options "-Dfile.encoding=\"utf-8\"" \ + --java-options "-Djava.net.useSystemProxies=true" \ --java-options "-Dcryptomator.logDir=\"@{userhome}/.local/share/Cryptomator/logs\"" \ --java-options "-Dcryptomator.pluginDir=\"@{userhome}/.local/share/Cryptomator/plugins\"" \ --java-options "-Dcryptomator.settingsPath=\"@{userhome}/.config/Cryptomator/settings.json:@{userhome}/.Cryptomator/settings.json\"" \ diff --git a/dist/mac/dmg/build.sh b/dist/mac/dmg/build.sh index 7330a873e..ef652ec7d 100755 --- a/dist/mac/dmg/build.sh +++ b/dist/mac/dmg/build.sh @@ -71,6 +71,7 @@ ${JAVA_HOME}/bin/jpackage \ --java-options "-Xss5m" \ --java-options "-Xmx256m" \ --java-options "-Dfile.encoding=\"utf-8\"" \ + --java-options "-Djava.net.useSystemProxies=true" \ --java-options "-Dapple.awt.enableTemplateImages=true" \ --java-options "-Dsun.java2d.metal=true" \ --java-options "-Dcryptomator.appVersion=\"${VERSION_NO}\"" \ diff --git a/dist/win/build.ps1 b/dist/win/build.ps1 index c630fffdd..48eeac2a6 100644 --- a/dist/win/build.ps1 +++ b/dist/win/build.ps1 @@ -102,6 +102,7 @@ if ($clean -and (Test-Path -Path $appPath)) { --java-options "-Dcryptomator.appVersion=`"$semVerNo`"" ` --app-version "$semVerNo.$revisionNo" ` --java-options "-Dfile.encoding=`"utf-8`"" ` + --java-options "-Djava.net.useSystemProxies=true" ` --java-options "-Dcryptomator.logDir=`"@{localappdata}/$AppName`"" ` --java-options "-Dcryptomator.pluginDir=`"@{appdata}/$AppName/Plugins`"" ` --java-options "-Dcryptomator.settingsPath=`"@{appdata}/$AppName/settings.json;@{userhome}/AppData/Roaming/$AppName/settings.json`"" ` diff --git a/src/main/java/org/cryptomator/ui/addvaultwizard/AddVaultModule.java b/src/main/java/org/cryptomator/ui/addvaultwizard/AddVaultModule.java index 02327aaf4..4a9dba7ad 100644 --- a/src/main/java/org/cryptomator/ui/addvaultwizard/AddVaultModule.java +++ b/src/main/java/org/cryptomator/ui/addvaultwizard/AddVaultModule.java @@ -5,21 +5,23 @@ import dagger.Module; import dagger.Provides; import dagger.multibindings.IntoMap; import org.cryptomator.common.vaults.Vault; +import org.cryptomator.ui.changepassword.NewPasswordController; +import org.cryptomator.ui.changepassword.PasswordStrengthUtil; 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.changepassword.NewPasswordController; -import org.cryptomator.ui.changepassword.PasswordStrengthUtil; import org.cryptomator.ui.common.StageFactory; import org.cryptomator.ui.fxapp.PrimaryStage; import org.cryptomator.ui.recoverykey.RecoveryKeyDisplayController; import javax.inject.Named; import javax.inject.Provider; +import javafx.beans.property.IntegerProperty; import javafx.beans.property.ObjectProperty; +import javafx.beans.property.SimpleIntegerProperty; import javafx.beans.property.SimpleObjectProperty; import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; @@ -65,6 +67,13 @@ public abstract class AddVaultModule { return new SimpleStringProperty(""); } + @Provides + @Named("shorteningThreshold") + @AddVaultWizardScoped + static IntegerProperty provideShorteningThreshold() { + return new SimpleIntegerProperty(CreateNewVaultExpertSettingsController.MAX_SHORTENING_THRESHOLD); + } + @Provides @AddVaultWizardWindow @AddVaultWizardScoped @@ -130,6 +139,13 @@ public abstract class AddVaultModule { return fxmlLoaders.createScene(FxmlFile.ADDVAULT_SUCCESS); } + @Provides + @FxmlScene(FxmlFile.ADDVAULT_NEW_EXPERT_SETTINGS) + @AddVaultWizardScoped + static Scene provideCreateNewVaultExpertSettingsScene(@AddVaultWizardWindow FxmlLoaderFactory fxmlLoaders) { + return fxmlLoaders.createScene(FxmlFile.ADDVAULT_NEW_EXPERT_SETTINGS); + } + // ------------------ @Binds @@ -181,4 +197,9 @@ public abstract class AddVaultModule { @FxControllerKey(AddVaultSuccessController.class) abstract FxController bindAddVaultSuccessController(AddVaultSuccessController controller); + @Binds + @IntoMap + @FxControllerKey(CreateNewVaultExpertSettingsController.class) + abstract FxController bindCreateNewVaultExpertSettingsController(CreateNewVaultExpertSettingsController controller); + } diff --git a/src/main/java/org/cryptomator/ui/addvaultwizard/CreateNewVaultExpertSettingsController.java b/src/main/java/org/cryptomator/ui/addvaultwizard/CreateNewVaultExpertSettingsController.java new file mode 100644 index 000000000..dbf0a0c6e --- /dev/null +++ b/src/main/java/org/cryptomator/ui/addvaultwizard/CreateNewVaultExpertSettingsController.java @@ -0,0 +1,118 @@ +package org.cryptomator.ui.addvaultwizard; + +import dagger.Lazy; +import org.cryptomator.ui.common.FxController; +import org.cryptomator.ui.common.FxmlFile; +import org.cryptomator.ui.common.FxmlScene; +import org.cryptomator.ui.controls.NumericTextField; + +import javax.inject.Inject; +import javax.inject.Named; +import javafx.application.Application; +import javafx.beans.binding.Bindings; +import javafx.beans.binding.BooleanBinding; +import javafx.beans.property.IntegerProperty; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.StringProperty; +import javafx.fxml.FXML; +import javafx.scene.Scene; +import javafx.scene.control.CheckBox; +import javafx.scene.control.Label; +import javafx.stage.Stage; +import java.nio.file.Path; + +@AddVaultWizardScoped +public class CreateNewVaultExpertSettingsController implements FxController { + + public static final int MAX_SHORTENING_THRESHOLD = 220; + public static final int MIN_SHORTENING_THRESHOLD = 36; + private static final String DOCS_NAME_SHORTENING_URL = "https://docs.cryptomator.org/en/1.7/security/architecture/#name-shortening"; + + private final Stage window; + private final Lazy application; + private final Lazy chooseLocationScene; + private final Lazy choosePasswordScene; + private final StringProperty vaultNameProperty; + private final ObjectProperty vaultPathProperty; + private final IntegerProperty shorteningThreshold; + + private final BooleanBinding validShorteningThreshold; + + //FXML + public Label vaultNameLabel; + public Label vaultPathLabel; + public CheckBox expertSettingsCheckBox; + public NumericTextField shorteningThresholdTextField; + + @Inject + CreateNewVaultExpertSettingsController(@AddVaultWizardWindow Stage window, // + Lazy application, // + @FxmlScene(FxmlFile.ADDVAULT_NEW_LOCATION) Lazy chooseLocationScene, // + @FxmlScene(FxmlFile.ADDVAULT_NEW_PASSWORD) Lazy choosePasswordScene, // + @Named("vaultName") StringProperty vaultName, // + ObjectProperty vaultPath, // + @Named("shorteningThreshold") IntegerProperty shorteningThreshold) { + this.window = window; + this.application = application; + this.chooseLocationScene = chooseLocationScene; + this.choosePasswordScene = choosePasswordScene; + this.vaultNameProperty = vaultName; + this.vaultPathProperty = vaultPath; + this.shorteningThreshold = shorteningThreshold; + this.validShorteningThreshold = Bindings.createBooleanBinding(this::isValidShorteningThreshold, shorteningThreshold); + } + + @FXML + public void initialize() { + vaultNameLabel.textProperty().bind(vaultNameProperty); + vaultPathLabel.textProperty().bind(vaultPathProperty.asString()); + shorteningThresholdTextField.setPromptText(MIN_SHORTENING_THRESHOLD + "-" + MAX_SHORTENING_THRESHOLD); + shorteningThresholdTextField.setText(Integer.toString(MAX_SHORTENING_THRESHOLD)); + shorteningThresholdTextField.textProperty().addListener((observable, oldValue, newValue) -> { + try { + int intValue = Integer.parseInt(newValue); + shorteningThreshold.set(intValue); + } catch (NumberFormatException e) { + shorteningThreshold.set(0); //the value is set to 0 to ensure that an invalid value assignment is detected during a NumberFormatException + } + }); + } + + @FXML + public void toggleUseExpertSettings() { + if (!expertSettingsCheckBox.isSelected()) { + shorteningThresholdTextField.setText(Integer.toString(MAX_SHORTENING_THRESHOLD)); + } + } + + @FXML + public void back() { + window.setScene(chooseLocationScene.get()); + } + + @FXML + public void next() { + window.setScene(choosePasswordScene.get()); + } + + public BooleanBinding validShorteningThresholdProperty() { + return validShorteningThreshold; + } + + public boolean isValidShorteningThreshold() { + var value = shorteningThreshold.get(); + return value >= MIN_SHORTENING_THRESHOLD && value <= MAX_SHORTENING_THRESHOLD; + } + + public void openDocs() { + application.get().getHostServices().showDocument(DOCS_NAME_SHORTENING_URL); + } + + public Path getVaultPath() { + return vaultPathProperty.get(); + } + + public String getVaultName() { + return vaultNameProperty.get(); + } +} \ No newline at end of file diff --git a/src/main/java/org/cryptomator/ui/addvaultwizard/CreateNewVaultLocationController.java b/src/main/java/org/cryptomator/ui/addvaultwizard/CreateNewVaultLocationController.java index 25febe5e1..3178f0ba4 100644 --- a/src/main/java/org/cryptomator/ui/addvaultwizard/CreateNewVaultLocationController.java +++ b/src/main/java/org/cryptomator/ui/addvaultwizard/CreateNewVaultLocationController.java @@ -48,7 +48,7 @@ public class CreateNewVaultLocationController implements FxController { private final Stage window; private final Lazy chooseNameScene; - private final Lazy choosePasswordScene; + private final Lazy chooseExpertSettingsScene; private final List locationPresetBtns; private final ObjectProperty vaultPath; private final StringProperty vaultName; @@ -68,10 +68,15 @@ public class CreateNewVaultLocationController implements FxController { public FontAwesome5IconView badLocation; @Inject - CreateNewVaultLocationController(@AddVaultWizardWindow Stage window, @FxmlScene(FxmlFile.ADDVAULT_NEW_NAME) Lazy chooseNameScene, @FxmlScene(FxmlFile.ADDVAULT_NEW_PASSWORD) Lazy choosePasswordScene, ObjectProperty vaultPath, @Named("vaultName") StringProperty vaultName, ResourceBundle resourceBundle) { + CreateNewVaultLocationController(@AddVaultWizardWindow Stage window, // + @FxmlScene(FxmlFile.ADDVAULT_NEW_NAME) Lazy chooseNameScene, // + @FxmlScene(FxmlFile.ADDVAULT_NEW_EXPERT_SETTINGS) Lazy chooseExpertSettingsScene, // + ObjectProperty vaultPath, // + @Named("vaultName") StringProperty vaultName, // + ResourceBundle resourceBundle) { this.window = window; this.chooseNameScene = chooseNameScene; - this.choosePasswordScene = choosePasswordScene; + this.chooseExpertSettingsScene = chooseExpertSettingsScene; this.vaultPath = vaultPath; this.vaultName = vaultName; this.resourceBundle = resourceBundle; @@ -151,7 +156,7 @@ public class CreateNewVaultLocationController implements FxController { @FXML public void next() { if (validVaultPath.getValue()) { - window.setScene(choosePasswordScene.get()); + window.setScene(chooseExpertSettingsScene.get()); } } diff --git a/src/main/java/org/cryptomator/ui/addvaultwizard/CreateNewVaultPasswordController.java b/src/main/java/org/cryptomator/ui/addvaultwizard/CreateNewVaultPasswordController.java index 81c6ce2da..28a73794a 100644 --- a/src/main/java/org/cryptomator/ui/addvaultwizard/CreateNewVaultPasswordController.java +++ b/src/main/java/org/cryptomator/ui/addvaultwizard/CreateNewVaultPasswordController.java @@ -10,13 +10,12 @@ import org.cryptomator.cryptolib.api.CryptorProvider; import org.cryptomator.cryptolib.api.Masterkey; import org.cryptomator.cryptolib.api.MasterkeyLoader; import org.cryptomator.cryptolib.common.MasterkeyFileAccess; +import org.cryptomator.ui.changepassword.NewPasswordController; import org.cryptomator.ui.common.FxController; import org.cryptomator.ui.common.FxmlFile; import org.cryptomator.ui.common.FxmlScene; -import org.cryptomator.ui.changepassword.NewPasswordController; import org.cryptomator.ui.common.Tasks; import org.cryptomator.ui.fxapp.FxApplicationWindows; -import org.cryptomator.ui.keyloading.masterkeyfile.MasterkeyFileLoadingStrategy; import org.cryptomator.ui.recoverykey.RecoveryKeyFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -26,6 +25,7 @@ import javax.inject.Named; import javafx.beans.binding.Bindings; import javafx.beans.binding.ObjectBinding; import javafx.beans.property.BooleanProperty; +import javafx.beans.property.IntegerProperty; import javafx.beans.property.ObjectProperty; import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.property.StringProperty; @@ -37,7 +37,6 @@ import javafx.scene.control.ToggleGroup; import javafx.stage.Stage; import java.io.IOException; import java.io.UncheckedIOException; -import java.net.URI; import java.nio.channels.WritableByteChannel; import java.nio.file.FileSystem; import java.nio.file.Files; @@ -57,7 +56,7 @@ public class CreateNewVaultPasswordController implements FxController { private static final Logger LOG = LoggerFactory.getLogger(CreateNewVaultPasswordController.class); private final Stage window; - private final Lazy chooseLocationScene; + private final Lazy chooseExpertSettingsScene; private final Lazy recoveryKeyScene; private final Lazy successScene; private final FxApplicationWindows appWindows; @@ -75,6 +74,7 @@ public class CreateNewVaultPasswordController implements FxController { private final BooleanProperty processing; private final BooleanProperty readyToCreateVault; private final ObjectBinding createVaultButtonState; + private final IntegerProperty shorteningThreshold; /* FXML */ public ToggleGroup recoveryKeyChoice; @@ -83,9 +83,25 @@ public class CreateNewVaultPasswordController implements FxController { public NewPasswordController newPasswordSceneController; @Inject - CreateNewVaultPasswordController(@AddVaultWizardWindow Stage window, @FxmlScene(FxmlFile.ADDVAULT_NEW_LOCATION) Lazy chooseLocationScene, @FxmlScene(FxmlFile.ADDVAULT_NEW_RECOVERYKEY) Lazy recoveryKeyScene, @FxmlScene(FxmlFile.ADDVAULT_SUCCESS) Lazy successScene, FxApplicationWindows appWindows, ExecutorService executor, RecoveryKeyFactory recoveryKeyFactory, @Named("vaultName") StringProperty vaultName, ObjectProperty vaultPath, @AddVaultWizardWindow ObjectProperty vault, @Named("recoveryKey") StringProperty recoveryKey, VaultListManager vaultListManager, ResourceBundle resourceBundle, ReadmeGenerator readmeGenerator, SecureRandom csprng, MasterkeyFileAccess masterkeyFileAccess) { + CreateNewVaultPasswordController(@AddVaultWizardWindow Stage window, // + @FxmlScene(FxmlFile.ADDVAULT_NEW_EXPERT_SETTINGS) Lazy chooseExpertSettingsScene, // + @FxmlScene(FxmlFile.ADDVAULT_NEW_RECOVERYKEY) Lazy recoveryKeyScene, // + @FxmlScene(FxmlFile.ADDVAULT_SUCCESS) Lazy successScene, // + FxApplicationWindows appWindows, // + ExecutorService executor, // + RecoveryKeyFactory recoveryKeyFactory, // + @Named("vaultName") StringProperty vaultName, // + ObjectProperty vaultPath, // + @AddVaultWizardWindow ObjectProperty vault, // + @Named("recoveryKey") StringProperty recoveryKey, // + VaultListManager vaultListManager, // + ResourceBundle resourceBundle, // + @Named("shorteningThreshold") IntegerProperty shorteningThreshold, // + ReadmeGenerator readmeGenerator, // + SecureRandom csprng, // + MasterkeyFileAccess masterkeyFileAccess) { this.window = window; - this.chooseLocationScene = chooseLocationScene; + this.chooseExpertSettingsScene = chooseExpertSettingsScene; this.recoveryKeyScene = recoveryKeyScene; this.successScene = successScene; this.appWindows = appWindows; @@ -103,6 +119,7 @@ public class CreateNewVaultPasswordController implements FxController { this.processing = new SimpleBooleanProperty(); this.readyToCreateVault = new SimpleBooleanProperty(); this.createVaultButtonState = Bindings.when(processing).then(ContentDisplay.LEFT).otherwise(ContentDisplay.TEXT_ONLY); + this.shorteningThreshold = shorteningThreshold; } @FXML @@ -116,7 +133,7 @@ public class CreateNewVaultPasswordController implements FxController { @FXML public void back() { - window.setScene(chooseLocationScene.get()); + window.setScene(chooseExpertSettingsScene.get()); } @FXML @@ -176,7 +193,11 @@ public class CreateNewVaultPasswordController implements FxController { // 2. initialize vault: try { MasterkeyLoader loader = ignored -> masterkey.copy(); - CryptoFileSystemProperties fsProps = CryptoFileSystemProperties.cryptoFileSystemProperties().withCipherCombo(CryptorProvider.Scheme.SIV_GCM).withKeyLoader(loader).build(); + CryptoFileSystemProperties fsProps = CryptoFileSystemProperties.cryptoFileSystemProperties() // + .withCipherCombo(CryptorProvider.Scheme.SIV_GCM) // + .withKeyLoader(loader) // + .withShorteningThreshold(shorteningThreshold.get()) // + .build(); CryptoFileSystemProvider.initialize(path, fsProps, DEFAULT_KEY_ID); // 3. write vault-internal readme file: diff --git a/src/main/java/org/cryptomator/ui/common/FxmlFile.java b/src/main/java/org/cryptomator/ui/common/FxmlFile.java index ea1209473..cefd424ff 100644 --- a/src/main/java/org/cryptomator/ui/common/FxmlFile.java +++ b/src/main/java/org/cryptomator/ui/common/FxmlFile.java @@ -4,6 +4,7 @@ public enum FxmlFile { ADDVAULT_EXISTING("/fxml/addvault_existing.fxml"), // ADDVAULT_NEW_NAME("/fxml/addvault_new_name.fxml"), // ADDVAULT_NEW_LOCATION("/fxml/addvault_new_location.fxml"), // + ADDVAULT_NEW_EXPERT_SETTINGS("/fxml/addvault_new_expert_settings.fxml"), // ADDVAULT_NEW_PASSWORD("/fxml/addvault_new_password.fxml"), // ADDVAULT_NEW_RECOVERYKEY("/fxml/addvault_new_recoverykey.fxml"), // ADDVAULT_SUCCESS("/fxml/addvault_success.fxml"), // diff --git a/src/main/java/org/cryptomator/ui/controls/FontAwesome5Icon.java b/src/main/java/org/cryptomator/ui/controls/FontAwesome5Icon.java index 77c3cb042..33a674b11 100644 --- a/src/main/java/org/cryptomator/ui/controls/FontAwesome5Icon.java +++ b/src/main/java/org/cryptomator/ui/controls/FontAwesome5Icon.java @@ -40,6 +40,7 @@ public enum FontAwesome5Icon { LOCK("\uF023"), // LOCK_OPEN("\uF3C1"), // MAGIC("\uF0D0"), // + PENCIL("\uF303"), // PLUS("\uF067"), // PRINT("\uF02F"), // QUESTION("\uF128"), // diff --git a/src/main/java/org/cryptomator/ui/controls/FormattedLabel.java b/src/main/java/org/cryptomator/ui/controls/FormattedLabel.java index 04ed7e477..4c0883cba 100644 --- a/src/main/java/org/cryptomator/ui/controls/FormattedLabel.java +++ b/src/main/java/org/cryptomator/ui/controls/FormattedLabel.java @@ -13,18 +13,19 @@ public class FormattedLabel extends Label { private final StringProperty format = new SimpleStringProperty(""); private final ObjectProperty arg1 = new SimpleObjectProperty<>(); private final ObjectProperty arg2 = new SimpleObjectProperty<>(); - // add arg2, arg3, ... on demand + private final ObjectProperty arg3 = new SimpleObjectProperty<>(); + // add arg4, arg5, ... on demand public FormattedLabel() { textProperty().bind(createStringBinding()); } protected StringBinding createStringBinding() { - return Bindings.createStringBinding(this::updateText, format, arg1, arg2); + return Bindings.createStringBinding(this::updateText, format, arg1, arg2, arg3); } private String updateText() { - return String.format(format.get(), arg1.get(), arg2.get()); + return String.format(format.get(), arg1.get(), arg2.get(), arg3.get()); } /* Observables */ @@ -64,4 +65,16 @@ public class FormattedLabel extends Label { public void setArg2(Object arg2) { this.arg2.set(arg2); } + + public ObjectProperty arg3Property() { + return arg3; + } + + public Object getArg3() { + return arg3.get(); + } + + public void setArg3(Object arg3) { + this.arg3.set(arg3); + } } diff --git a/src/main/java/org/cryptomator/ui/fxapp/FxApplicationModule.java b/src/main/java/org/cryptomator/ui/fxapp/FxApplicationModule.java index cc1f34e4b..aec7aa0d1 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.health.HealthCheckComponent; import org.cryptomator.ui.lock.LockComponent; import org.cryptomator.ui.mainwindow.MainWindowComponent; import org.cryptomator.ui.preferences.PreferencesComponent; @@ -15,12 +16,13 @@ import org.cryptomator.ui.quit.QuitComponent; import org.cryptomator.ui.traymenu.TrayMenuComponent; import org.cryptomator.ui.unlock.UnlockComponent; import org.cryptomator.ui.updatereminder.UpdateReminderComponent; +import org.cryptomator.ui.vaultoptions.VaultOptionsComponent; import javafx.scene.image.Image; import java.io.IOException; import java.io.InputStream; -@Module(includes = {UpdateCheckerModule.class}, subcomponents = {TrayMenuComponent.class, MainWindowComponent.class, PreferencesComponent.class, UnlockComponent.class, LockComponent.class, QuitComponent.class, ErrorComponent.class, UpdateReminderComponent.class}) +@Module(includes = {UpdateCheckerModule.class}, subcomponents = {TrayMenuComponent.class, MainWindowComponent.class, PreferencesComponent.class, VaultOptionsComponent.class, UnlockComponent.class, LockComponent.class, QuitComponent.class, ErrorComponent.class, HealthCheckComponent.class, UpdateReminderComponent.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 45cd7d2cb..4b074e0aa 100644 --- a/src/main/java/org/cryptomator/ui/fxapp/FxApplicationWindows.java +++ b/src/main/java/org/cryptomator/ui/fxapp/FxApplicationWindows.java @@ -14,6 +14,8 @@ import org.cryptomator.ui.quit.QuitComponent; import org.cryptomator.ui.unlock.UnlockComponent; import org.cryptomator.ui.unlock.UnlockWorkflow; import org.cryptomator.ui.updatereminder.UpdateReminderComponent; +import org.cryptomator.ui.vaultoptions.SelectedVaultOptionsTab; +import org.cryptomator.ui.vaultoptions.VaultOptionsComponent; import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -48,6 +50,7 @@ public class FxApplicationWindows { private final LockComponent.Factory lockWorkflowFactory; private final ErrorComponent.Factory errorWindowFactory; private final ExecutorService executor; + private final VaultOptionsComponent.Factory vaultOptionsWindow; private final FilteredList visibleWindows; @Inject @@ -60,6 +63,7 @@ public class FxApplicationWindows { UpdateReminderComponent.Builder updateReminderWindowBuilder, // LockComponent.Factory lockWorkflowFactory, // ErrorComponent.Factory errorWindowFactory, // + VaultOptionsComponent.Factory vaultOptionsWindow, // ExecutorService executor) { this.primaryStage = primaryStage; this.trayIntegration = trayIntegration; @@ -71,6 +75,7 @@ public class FxApplicationWindows { this.lockWorkflowFactory = lockWorkflowFactory; this.errorWindowFactory = errorWindowFactory; this.executor = executor; + this.vaultOptionsWindow = vaultOptionsWindow; this.visibleWindows = Window.getWindows().filtered(Window::isShowing); } @@ -117,6 +122,10 @@ public class FxApplicationWindows { return CompletableFuture.supplyAsync(() -> preferencesWindow.get().showPreferencesWindow(selectedTab), Platform::runLater).whenComplete(this::reportErrors); } + public CompletionStage showVaultOptionsWindow(Vault vault, SelectedVaultOptionsTab tab) { + return showMainWindow().thenApplyAsync((window) -> vaultOptionsWindow.create(vault).showVaultOptionsWindow(tab), Platform::runLater).whenComplete(this::reportErrors); + } + public void showQuitWindow(QuitResponse response, boolean forced) { CompletableFuture.runAsync(() -> quitWindowBuilder.build().showQuitWindow(response,forced), Platform::runLater); } diff --git a/src/main/java/org/cryptomator/ui/mainwindow/MainWindowModule.java b/src/main/java/org/cryptomator/ui/mainwindow/MainWindowModule.java index 6fbb8e16e..0b403bb47 100644 --- a/src/main/java/org/cryptomator/ui/mainwindow/MainWindowModule.java +++ b/src/main/java/org/cryptomator/ui/mainwindow/MainWindowModule.java @@ -19,7 +19,6 @@ import org.cryptomator.ui.health.HealthCheckComponent; import org.cryptomator.ui.migration.MigrationComponent; import org.cryptomator.ui.removevault.RemoveVaultComponent; import org.cryptomator.ui.stats.VaultStatisticsComponent; -import org.cryptomator.ui.vaultoptions.VaultOptionsComponent; import org.cryptomator.ui.wrongfilealert.WrongFileAlertComponent; import javax.inject.Named; @@ -33,7 +32,7 @@ import javafx.stage.StageStyle; import java.util.Map; import java.util.ResourceBundle; -@Module(subcomponents = {AddVaultWizardComponent.class, HealthCheckComponent.class, MigrationComponent.class, RemoveVaultComponent.class, VaultOptionsComponent.class, VaultStatisticsComponent.class, WrongFileAlertComponent.class, ErrorComponent.class}) +@Module(subcomponents = {AddVaultWizardComponent.class, MigrationComponent.class, RemoveVaultComponent.class, VaultStatisticsComponent.class, WrongFileAlertComponent.class, ErrorComponent.class}) abstract class MainWindowModule { @Provides diff --git a/src/main/java/org/cryptomator/ui/unlock/UnlockInvalidMountPointController.java b/src/main/java/org/cryptomator/ui/unlock/UnlockInvalidMountPointController.java index b07e3ffde..83bd80df4 100644 --- a/src/main/java/org/cryptomator/ui/unlock/UnlockInvalidMountPointController.java +++ b/src/main/java/org/cryptomator/ui/unlock/UnlockInvalidMountPointController.java @@ -8,6 +8,7 @@ import org.cryptomator.ui.common.FxController; import org.cryptomator.ui.controls.FormattedLabel; import org.cryptomator.ui.fxapp.FxApplicationWindows; import org.cryptomator.ui.preferences.SelectedPreferencesTab; +import org.cryptomator.ui.vaultoptions.SelectedVaultOptionsTab; import javax.inject.Inject; import javafx.fxml.FXML; @@ -21,9 +22,10 @@ public class UnlockInvalidMountPointController implements FxController { private final Stage window; private final Vault vault; - private final AtomicReference unlockException; private final FxApplicationWindows appWindows; private final ResourceBundle resourceBundle; + private final ExceptionType exceptionType; + private final String exceptionMessage; public FormattedLabel dialogDescription; @@ -31,22 +33,18 @@ public class UnlockInvalidMountPointController implements FxController { UnlockInvalidMountPointController(@UnlockWindow Stage window, @UnlockWindow Vault vault, @UnlockWindow AtomicReference unlockException, FxApplicationWindows appWindows, ResourceBundle resourceBundle) { this.window = window; this.vault = vault; - this.unlockException = unlockException; this.appWindows = appWindows; this.resourceBundle = resourceBundle; + + var exc = unlockException.get(); + this.exceptionType = getExceptionType(exc); + this.exceptionMessage = exc.getMessage(); } @FXML public void initialize() { - var e = unlockException.get(); - var translationKey = switch (e) { - case MountPointNotSupportedException x -> "unlock.error.customPath.description.notSupported"; - case MountPointNotExistsException x -> "unlock.error.customPath.description.notExists"; - case MountPointInUseException x -> "unlock.error.customPath.description.inUse"; - default -> "unlock.error.customPath.description.generic"; - }; - dialogDescription.setFormat(resourceBundle.getString(translationKey)); - dialogDescription.setArg1(e.getMessage()); + dialogDescription.setFormat(resourceBundle.getString(exceptionType.translationKey)); + dialogDescription.setArg1(exceptionMessage); } @FXML @@ -60,4 +58,51 @@ public class UnlockInvalidMountPointController implements FxController { window.close(); } + @FXML + public void closeAndOpenVaultOptions() { + appWindows.showVaultOptionsWindow(vault, SelectedVaultOptionsTab.MOUNT); + window.close(); + } + + private ExceptionType getExceptionType(Throwable unlockException) { + return switch (unlockException) { + case MountPointNotSupportedException x -> ExceptionType.NOT_SUPPORTED; + case MountPointNotExistsException x -> ExceptionType.NOT_EXISTING; + case MountPointInUseException x -> ExceptionType.IN_USE; + default -> ExceptionType.GENERIC; + }; + } + + private enum ExceptionType { + + NOT_SUPPORTED("unlock.error.customPath.description.notSupported", ButtonAction.SHOW_PREFERENCES), + NOT_EXISTING("unlock.error.customPath.description.notExists", ButtonAction.SHOW_VAULT_OPTIONS), + IN_USE("unlock.error.customPath.description.inUse", ButtonAction.SHOW_VAULT_OPTIONS), + GENERIC("unlock.error.customPath.description.generic", ButtonAction.SHOW_PREFERENCES); + + private final String translationKey; + private final ButtonAction action; + + ExceptionType(String translationKey, ButtonAction action) { + this.translationKey = translationKey; + this.action = action; + } + } + + private enum ButtonAction { + + SHOW_PREFERENCES, + SHOW_VAULT_OPTIONS; + + } + + /* Getter */ + + public boolean isShowPreferences() { + return exceptionType.action == ButtonAction.SHOW_PREFERENCES; + } + + public boolean isShowVaultOptions() { + return exceptionType.action == ButtonAction.SHOW_VAULT_OPTIONS; + } } \ No newline at end of file diff --git a/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsComponent.java b/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsComponent.java index ac749132a..4f4de613b 100644 --- a/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsComponent.java +++ b/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsComponent.java @@ -28,12 +28,13 @@ public interface VaultOptionsComponent { ObjectProperty selectedTabProperty(); - default void showVaultOptionsWindow(SelectedVaultOptionsTab selectedTab) { + default Stage showVaultOptionsWindow(SelectedVaultOptionsTab selectedTab) { selectedTabProperty().set(selectedTab); Stage stage = window(); stage.setScene(scene().get()); stage.show(); stage.requestFocus(); + return stage; } @Subcomponent.Factory diff --git a/src/main/resources/fxml/addvault_new_expert_settings.fxml b/src/main/resources/fxml/addvault_new_expert_settings.fxml new file mode 100644 index 000000000..202f7c4d7 --- /dev/null +++ b/src/main/resources/fxml/addvault_new_expert_settings.fxml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +