mirror of
https://github.com/cryptomator/cryptomator.git
synced 2026-05-14 08:41:28 +00:00
Merge branch 'develop' into release/1.10.0
This commit is contained in:
4
.github/dependabot.yml
vendored
4
.github/dependabot.yml
vendored
@@ -8,7 +8,7 @@ updates:
|
||||
time: "06:00"
|
||||
timezone: "UTC"
|
||||
groups:
|
||||
all: # one PR for all dependencies
|
||||
maven-dependencies:
|
||||
patterns:
|
||||
- "*"
|
||||
|
||||
@@ -17,7 +17,7 @@ updates:
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
groups:
|
||||
all: # one PR for all actions
|
||||
github-actions:
|
||||
patterns:
|
||||
- "*"
|
||||
labels:
|
||||
|
||||
BIN
dist/mac/resources/Cryptomator.icns
vendored
BIN
dist/mac/resources/Cryptomator.icns
vendored
Binary file not shown.
2
dist/win/contrib/patchWebDAV.bat
vendored
2
dist/win/contrib/patchWebDAV.bat
vendored
@@ -3,5 +3,5 @@
|
||||
::REPLACE ME
|
||||
|
||||
cd %~dp0
|
||||
powershell -NoLogo -NoProfile -NonInteractive -ExecutionPolicy Unrestricted -Command .\patchWebDAV.ps1^
|
||||
powershell -NoLogo -NoProfile -NonInteractive -ExecutionPolicy RemoteSigned -Command .\patchWebDAV.ps1^
|
||||
-LoopbackAlias %LOOPBACK_ALIAS%
|
||||
@@ -2,4 +2,4 @@
|
||||
:: see comments in file ./version170-migrate-settings.ps1
|
||||
|
||||
cd %~dp0
|
||||
powershell -NoLogo -NoProfile -NonInteractive -ExecutionPolicy Unrestricted -Command .\version170-migrate-settings.ps1
|
||||
powershell -NoLogo -NoProfile -NonInteractive -ExecutionPolicy RemoteSigned -Command .\version170-migrate-settings.ps1
|
||||
|
||||
59
pom.xml
59
pom.xml
@@ -36,35 +36,42 @@
|
||||
<cryptomator.cryptofs.version>2.6.7</cryptomator.cryptofs.version>
|
||||
<cryptomator.integrations.version>1.3.0</cryptomator.integrations.version>
|
||||
<cryptomator.integrations.win.version>1.2.2</cryptomator.integrations.win.version>
|
||||
<cryptomator.integrations.mac.version>1.2.0</cryptomator.integrations.mac.version>
|
||||
<cryptomator.integrations.mac.version>1.2.1</cryptomator.integrations.mac.version>
|
||||
<cryptomator.integrations.linux.version>1.3.0-beta6</cryptomator.integrations.linux.version>
|
||||
<cryptomator.fuse.version>3.0.0</cryptomator.fuse.version>
|
||||
<cryptomator.dokany.version>2.0.0</cryptomator.dokany.version>
|
||||
<cryptomator.webdav.version>2.0.3</cryptomator.webdav.version>
|
||||
|
||||
<!-- 3rd party dependencies -->
|
||||
<commons-lang3.version>3.12.0</commons-lang3.version>
|
||||
<dagger.version>2.45</dagger.version>
|
||||
<commons-lang3.version>3.13.0</commons-lang3.version>
|
||||
<dagger.version>2.47</dagger.version>
|
||||
<easybind.version>2.2</easybind.version>
|
||||
<guava.version>32.0.1-jre</guava.version>
|
||||
<guava.version>32.1.2-jre</guava.version>
|
||||
<jackson.version>2.15.2</jackson.version>
|
||||
<javafx.version>20.0.2</javafx.version>
|
||||
<jwt.version>4.4.0</jwt.version>
|
||||
<nimbus-jose.version>9.31</nimbus-jose.version>
|
||||
<logback.version>1.4.7</logback.version>
|
||||
<logback.version>1.4.11</logback.version>
|
||||
<slf4j.version>2.0.7</slf4j.version>
|
||||
<tinyoauth2.version>0.5.1</tinyoauth2.version>
|
||||
<zxcvbn.version>1.7.0</zxcvbn.version>
|
||||
<tinyoauth2.version>0.6.0</tinyoauth2.version>
|
||||
<zxcvbn.version>1.8.2</zxcvbn.version>
|
||||
|
||||
<!-- test dependencies -->
|
||||
<junit.jupiter.version>5.9.3</junit.jupiter.version>
|
||||
<mockito.version>5.3.1</mockito.version>
|
||||
<junit.jupiter.version>5.10.0</junit.jupiter.version>
|
||||
<mockito.version>5.5.0</mockito.version>
|
||||
<hamcrest.version>2.2</hamcrest.version>
|
||||
|
||||
<!-- build-time dependencies -->
|
||||
<jetbrains.annotations.version>23.0.0</jetbrains.annotations.version>
|
||||
<dependency-check.version>8.1.2</dependency-check.version>
|
||||
<jacoco.version>0.8.9</jacoco.version>
|
||||
<jetbrains.annotations.version>24.0.1</jetbrains.annotations.version>
|
||||
<dependency-check.version>8.4.0</dependency-check.version>
|
||||
<jacoco.version>0.8.10</jacoco.version>
|
||||
<license-generator.version>2.2.0</license-generator.version>
|
||||
<junit-tree-reporter.version>1.2.1</junit-tree-reporter.version>
|
||||
<mvn-compiler.version>3.11.0</mvn-compiler.version>
|
||||
<mvn-resources.version>3.3.1</mvn-resources.version>
|
||||
<mvn-dependency.version>3.6.0</mvn-dependency.version>
|
||||
<mvn-surefire.version>3.1.2</mvn-surefire.version>
|
||||
<mvn-jar.version>3.3.0</mvn-jar.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
@@ -240,7 +247,7 @@
|
||||
<dependency>
|
||||
<groupId>com.google.jimfs</groupId>
|
||||
<artifactId>jimfs</artifactId>
|
||||
<version>1.2</version>
|
||||
<version>1.3.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -258,32 +265,32 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.10.1</version>
|
||||
<version>${mvn-compiler.version}</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-resources-plugin</artifactId>
|
||||
<version>3.3.0</version>
|
||||
<version>${mvn-resources.version}</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
<version>3.3.0</version>
|
||||
<version>${mvn-dependency.version}</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>3.0.0-M7</version>
|
||||
<version>${mvn-surefire.version}</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>license-maven-plugin</artifactId>
|
||||
<version>2.0.0</version>
|
||||
<version>${license-generator.version}</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>3.3.0</version>
|
||||
<version>${mvn-jar.version}</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.jacoco</groupId>
|
||||
@@ -332,8 +339,22 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>me.fabriciorby</groupId>
|
||||
<artifactId>maven-surefire-junit5-tree-reporter</artifactId>
|
||||
<version>${junit-tree-reporter.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<configuration>
|
||||
<argLine>--enable-preview</argLine>
|
||||
<reportFormat>plain</reportFormat>
|
||||
<consoleOutputReporter>
|
||||
<disable>true</disable>
|
||||
</consoleOutputReporter>
|
||||
<statelessTestsetInfoReporter
|
||||
implementation="org.apache.maven.plugin.surefire.extensions.junit5.JUnit5StatelessTestsetInfoTreeReporter">
|
||||
</statelessTestsetInfoReporter>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
|
||||
@@ -65,7 +65,6 @@ public class Settings {
|
||||
public final IntegerProperty windowYPosition;
|
||||
public final IntegerProperty windowWidth;
|
||||
public final IntegerProperty windowHeight;
|
||||
public final StringProperty displayConfiguration;
|
||||
public final StringProperty language;
|
||||
public final StringProperty mountService;
|
||||
public final StringProperty lastUpdateCheck;
|
||||
@@ -103,7 +102,6 @@ public class Settings {
|
||||
this.windowYPosition = new SimpleIntegerProperty(this, "windowYPosition", json.windowYPosition);
|
||||
this.windowWidth = new SimpleIntegerProperty(this, "windowWidth", json.windowWidth);
|
||||
this.windowHeight = new SimpleIntegerProperty(this, "windowHeight", json.windowHeight);
|
||||
this.displayConfiguration = new SimpleStringProperty(this, "displayConfiguration", json.displayConfiguration);
|
||||
this.language = new SimpleStringProperty(this, "language", json.language);
|
||||
this.mountService = new SimpleStringProperty(this, "mountService", json.mountService);
|
||||
this.lastUpdateCheck = new SimpleStringProperty(this, "lastUpdateCheck", json.lastUpdateCheck);
|
||||
@@ -131,7 +129,6 @@ public class Settings {
|
||||
windowYPosition.addListener(this::somethingChanged);
|
||||
windowWidth.addListener(this::somethingChanged);
|
||||
windowHeight.addListener(this::somethingChanged);
|
||||
displayConfiguration.addListener(this::somethingChanged);
|
||||
language.addListener(this::somethingChanged);
|
||||
mountService.addListener(this::somethingChanged);
|
||||
lastUpdateCheck.addListener(this::somethingChanged);
|
||||
@@ -186,7 +183,6 @@ public class Settings {
|
||||
json.windowYPosition = windowYPosition.get();
|
||||
json.windowWidth = windowWidth.get();
|
||||
json.windowHeight = windowHeight.get();
|
||||
json.displayConfiguration = displayConfiguration.get();
|
||||
json.language = language.get();
|
||||
json.mountService = mountService.get();
|
||||
json.lastUpdateCheck = lastUpdateCheck.get();
|
||||
|
||||
@@ -31,9 +31,6 @@ class SettingsJson {
|
||||
@JsonProperty("theme")
|
||||
UiTheme theme = Settings.DEFAULT_THEME;
|
||||
|
||||
@JsonProperty("displayConfiguration")
|
||||
String displayConfiguration;
|
||||
|
||||
@JsonProperty("keychainProvider")
|
||||
String keychainProvider = Settings.DEFAULT_KEYCHAIN_PROVIDER;
|
||||
|
||||
|
||||
@@ -45,9 +45,8 @@ public abstract class AddVaultModule {
|
||||
@Provides
|
||||
@AddVaultWizardWindow
|
||||
@AddVaultWizardScoped
|
||||
static Stage provideStage(StageFactory factory, @PrimaryStage Stage primaryStage, ResourceBundle resourceBundle) {
|
||||
static Stage provideStage(StageFactory factory, @PrimaryStage Stage primaryStage) {
|
||||
Stage stage = factory.create();
|
||||
stage.setTitle(resourceBundle.getString("addvaultwizard.title"));
|
||||
stage.setResizable(false);
|
||||
stage.initModality(Modality.WINDOW_MODAL);
|
||||
stage.initOwner(primaryStage);
|
||||
@@ -90,13 +89,6 @@ public abstract class AddVaultModule {
|
||||
|
||||
// ------------------
|
||||
|
||||
@Provides
|
||||
@FxmlScene(FxmlFile.ADDVAULT_WELCOME)
|
||||
@AddVaultWizardScoped
|
||||
static Scene provideWelcomeScene(@AddVaultWizardWindow FxmlLoaderFactory fxmlLoaders) {
|
||||
return fxmlLoaders.createScene(FxmlFile.ADDVAULT_WELCOME);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@FxmlScene(FxmlFile.ADDVAULT_EXISTING)
|
||||
@AddVaultWizardScoped
|
||||
@@ -148,11 +140,6 @@ public abstract class AddVaultModule {
|
||||
|
||||
// ------------------
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@FxControllerKey(AddVaultWelcomeController.class)
|
||||
abstract FxController bindWelcomeController(AddVaultWelcomeController controller);
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@FxControllerKey(ChooseExistingVaultController.class)
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
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.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
@AddVaultWizardScoped
|
||||
public class AddVaultWelcomeController implements FxController {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(AddVaultWelcomeController.class);
|
||||
private final Stage window;
|
||||
private final Lazy<Scene> chooseExistingVaultScene;
|
||||
private final Lazy<Scene> createNewVaultScene;
|
||||
|
||||
@Inject
|
||||
AddVaultWelcomeController(@AddVaultWizardWindow Stage window, @FxmlScene(FxmlFile.ADDVAULT_EXISTING) Lazy<Scene> chooseExistingVaultScene, @FxmlScene(FxmlFile.ADDVAULT_NEW_NAME) Lazy<Scene> createNewVaultScene) {
|
||||
this.window = window;
|
||||
this.chooseExistingVaultScene = chooseExistingVaultScene;
|
||||
this.createNewVaultScene = createNewVaultScene;
|
||||
}
|
||||
|
||||
public void createNewVault() {
|
||||
LOG.debug("AddVaultWelcomeController.createNewVault()");
|
||||
window.setScene(createNewVaultScene.get());
|
||||
}
|
||||
|
||||
public void chooseExistingVault() {
|
||||
LOG.debug("AddVaultWelcomeController.chooseExistingVault()");
|
||||
window.setScene(chooseExistingVaultScene.get());
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,7 @@ import org.cryptomator.ui.common.FxmlScene;
|
||||
|
||||
import javafx.scene.Scene;
|
||||
import javafx.stage.Stage;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
@AddVaultWizardScoped
|
||||
@Subcomponent(modules = {AddVaultModule.class})
|
||||
@@ -20,12 +21,23 @@ public interface AddVaultWizardComponent {
|
||||
@AddVaultWizardWindow
|
||||
Stage window();
|
||||
|
||||
@FxmlScene(FxmlFile.ADDVAULT_WELCOME)
|
||||
Lazy<Scene> scene();
|
||||
@FxmlScene(FxmlFile.ADDVAULT_NEW_NAME)
|
||||
Lazy<Scene> sceneNew();
|
||||
@FxmlScene(FxmlFile.ADDVAULT_EXISTING)
|
||||
Lazy<Scene> sceneExisting();
|
||||
|
||||
default void showAddVaultWizard() {
|
||||
default void showAddNewVaultWizard(ResourceBundle resourceBundle) {
|
||||
Stage stage = window();
|
||||
stage.setScene(scene().get());
|
||||
stage.setScene(sceneNew().get());
|
||||
stage.setTitle(resourceBundle.getString("addvaultwizard.new.title"));
|
||||
stage.sizeToScene();
|
||||
stage.show();
|
||||
}
|
||||
|
||||
default void showAddExistingVaultWizard(ResourceBundle resourceBundle) {
|
||||
Stage stage = window();
|
||||
stage.setScene(sceneExisting().get());
|
||||
stage.setTitle(resourceBundle.getString("addvaultwizard.existing.title"));
|
||||
stage.sizeToScene();
|
||||
stage.show();
|
||||
}
|
||||
|
||||
@@ -35,7 +35,6 @@ public class ChooseExistingVaultController implements FxController {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ChooseExistingVaultController.class);
|
||||
|
||||
private final Stage window;
|
||||
private final Lazy<Scene> welcomeScene;
|
||||
private final Lazy<Scene> successScene;
|
||||
private final FxApplicationWindows appWindows;
|
||||
private final ObjectProperty<Path> vaultPath;
|
||||
@@ -45,9 +44,15 @@ public class ChooseExistingVaultController implements FxController {
|
||||
private final ObservableValue<Image> screenshot;
|
||||
|
||||
@Inject
|
||||
ChooseExistingVaultController(@AddVaultWizardWindow Stage window, @FxmlScene(FxmlFile.ADDVAULT_WELCOME) Lazy<Scene> welcomeScene, @FxmlScene(FxmlFile.ADDVAULT_SUCCESS) Lazy<Scene> successScene, FxApplicationWindows appWindows, ObjectProperty<Path> vaultPath, @AddVaultWizardWindow ObjectProperty<Vault> vault, VaultListManager vaultListManager, ResourceBundle resourceBundle, FxApplicationStyle applicationStyle) {
|
||||
ChooseExistingVaultController(@AddVaultWizardWindow Stage window, //
|
||||
@FxmlScene(FxmlFile.ADDVAULT_SUCCESS) Lazy<Scene> successScene, //
|
||||
FxApplicationWindows appWindows, //
|
||||
ObjectProperty<Path> vaultPath, //
|
||||
@AddVaultWizardWindow ObjectProperty<Vault> vault, //
|
||||
VaultListManager vaultListManager, //
|
||||
ResourceBundle resourceBundle, //
|
||||
FxApplicationStyle applicationStyle) {
|
||||
this.window = window;
|
||||
this.welcomeScene = welcomeScene;
|
||||
this.successScene = successScene;
|
||||
this.appWindows = appWindows;
|
||||
this.vaultPath = vaultPath;
|
||||
@@ -70,11 +75,6 @@ public class ChooseExistingVaultController implements FxController {
|
||||
return new Image((Objects.requireNonNull(getClass().getResource(imageResourcePath)).toString()));
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void back() {
|
||||
window.setScene(welcomeScene.get());
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void chooseFileAndNext() {
|
||||
FileChooser fileChooser = new FileChooser();
|
||||
|
||||
@@ -17,7 +17,6 @@ import javafx.scene.Scene;
|
||||
import javafx.scene.control.TextField;
|
||||
import javafx.stage.Stage;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@AddVaultWizardScoped
|
||||
@@ -27,16 +26,17 @@ public class CreateNewVaultNameController implements FxController {
|
||||
|
||||
public TextField textField;
|
||||
private final Stage window;
|
||||
private final Lazy<Scene> welcomeScene;
|
||||
private final Lazy<Scene> chooseLocationScene;
|
||||
private final ObjectProperty<Path> vaultPath;
|
||||
private final StringProperty vaultName;
|
||||
private final BooleanBinding validVaultName;
|
||||
|
||||
@Inject
|
||||
CreateNewVaultNameController(@AddVaultWizardWindow Stage window, @FxmlScene(FxmlFile.ADDVAULT_WELCOME) Lazy<Scene> welcomeScene, @FxmlScene(FxmlFile.ADDVAULT_NEW_LOCATION) Lazy<Scene> chooseLocationScene, ObjectProperty<Path> vaultPath, @Named("vaultName") StringProperty vaultName, ResourceBundle resourceBundle) {
|
||||
CreateNewVaultNameController(@AddVaultWizardWindow Stage window, //
|
||||
@FxmlScene(FxmlFile.ADDVAULT_NEW_LOCATION) Lazy<Scene> chooseLocationScene, //
|
||||
ObjectProperty<Path> vaultPath, //
|
||||
@Named("vaultName") StringProperty vaultName) {
|
||||
this.window = window;
|
||||
this.welcomeScene = welcomeScene;
|
||||
this.chooseLocationScene = chooseLocationScene;
|
||||
this.vaultPath = vaultPath;
|
||||
this.vaultName = vaultName;
|
||||
@@ -58,11 +58,6 @@ public class CreateNewVaultNameController implements FxController {
|
||||
}
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void back() {
|
||||
window.setScene(welcomeScene.get());
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void next() {
|
||||
window.setScene(chooseLocationScene.get());
|
||||
|
||||
@@ -8,7 +8,6 @@ public enum FxmlFile {
|
||||
ADDVAULT_NEW_PASSWORD("/fxml/addvault_new_password.fxml"), //
|
||||
ADDVAULT_NEW_RECOVERYKEY("/fxml/addvault_new_recoverykey.fxml"), //
|
||||
ADDVAULT_SUCCESS("/fxml/addvault_success.fxml"), //
|
||||
ADDVAULT_WELCOME("/fxml/addvault_welcome.fxml"), //
|
||||
CHANGEPASSWORD("/fxml/changepassword.fxml"), //
|
||||
CONVERTVAULT_HUBTOPASSWORD_START("/fxml/convertvault_hubtopassword_start.fxml"), //
|
||||
CONVERTVAULT_HUBTOPASSWORD_CONVERT("/fxml/convertvault_hubtopassword_convert.fxml"), //
|
||||
|
||||
@@ -47,14 +47,15 @@ public class ErrorController implements FxController {
|
||||
private static final String REPORT_URL_FORMAT = "https://github.com/cryptomator/cryptomator/discussions/new?category=Errors&title=Error+%s&body=%s";
|
||||
private static final String SEARCH_ERRORCODE_DELIM = " OR ";
|
||||
private static final String REPORT_BODY_TEMPLATE = """
|
||||
<!-- 💚 Thank you for reporting this error. -->
|
||||
OS: %s / %s
|
||||
App: %s / %s
|
||||
|
||||
<!-- ✏ Please describe what happened as accurately as possible. -->
|
||||
|
||||
<!-- 📋 Please also copy and paste the detail text from the error window. -->
|
||||
|
||||
<!-- ℹ Text enclosed like this (chevrons, exclamation mark, two dashes) is not visible to others! -->
|
||||
Description:
|
||||
|
||||
<!-- 📋 Please also copy and paste the details from the error window. -->
|
||||
Details:
|
||||
|
||||
<!-- ❗ If the description or the detail text is missing, the discussion will be deleted. -->
|
||||
""";
|
||||
|
||||
@@ -16,6 +16,7 @@ import javafx.stage.Stage;
|
||||
public class MainWindowSceneFactory extends DefaultSceneFactory {
|
||||
|
||||
protected static final KeyCodeCombination SHORTCUT_N = new KeyCodeCombination(KeyCode.N, KeyCombination.SHORTCUT_DOWN);
|
||||
protected static final KeyCodeCombination SHORTCUT_O = new KeyCodeCombination(KeyCode.O, KeyCombination.SHORTCUT_DOWN);
|
||||
|
||||
private final Lazy<MainWindowTitleController> mainWindowTitleController;
|
||||
private final Lazy<VaultListController> vaultListController;
|
||||
@@ -34,6 +35,7 @@ public class MainWindowSceneFactory extends DefaultSceneFactory {
|
||||
} else {
|
||||
scene.getAccelerators().put(SHORTCUT_W, mainWindowTitleController.get()::close);
|
||||
}
|
||||
scene.getAccelerators().put(SHORTCUT_N, vaultListController.get()::didClickAddVault);
|
||||
scene.getAccelerators().put(SHORTCUT_N, vaultListController.get()::didClickAddNewVault);
|
||||
scene.getAccelerators().put(SHORTCUT_O, vaultListController.get()::didClickAddExistingVault);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javafx.beans.binding.Bindings;
|
||||
import javafx.beans.binding.BooleanBinding;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.fxml.FXML;
|
||||
@@ -15,6 +14,7 @@ import javafx.scene.input.MouseEvent;
|
||||
import javafx.scene.layout.Region;
|
||||
import javafx.stage.Screen;
|
||||
import javafx.stage.Stage;
|
||||
import javafx.stage.WindowEvent;
|
||||
|
||||
@MainWindow
|
||||
public class ResizeController implements FxController {
|
||||
@@ -53,48 +53,70 @@ public class ResizeController implements FxController {
|
||||
public void initialize() {
|
||||
LOG.trace("init ResizeController");
|
||||
|
||||
if (neverTouched()) {
|
||||
settings.displayConfiguration.set(getMonitorSizes());
|
||||
return;
|
||||
} else {
|
||||
if (didDisplayConfigurationChange()) {
|
||||
//If the position is illegal, then the window appears on the main screen in the middle of the window.
|
||||
Rectangle2D primaryScreenBounds = Screen.getPrimary().getBounds();
|
||||
window.setX((primaryScreenBounds.getWidth() - window.getMinWidth()) / 2);
|
||||
window.setY((primaryScreenBounds.getHeight() - window.getMinHeight()) / 2);
|
||||
window.setWidth(window.getMinWidth());
|
||||
window.setHeight(window.getMinHeight());
|
||||
} else {
|
||||
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());
|
||||
}
|
||||
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());
|
||||
}
|
||||
savePositionalSettings();
|
||||
|
||||
window.setOnShowing(this::checkDisplayBounds);
|
||||
}
|
||||
|
||||
private boolean neverTouched() {
|
||||
return (settings.windowHeight.get() == 0) && (settings.windowWidth.get() == 0) && (settings.windowXPosition.get() == 0) && (settings.windowYPosition.get() == 0);
|
||||
}
|
||||
|
||||
private boolean didDisplayConfigurationChange() {
|
||||
String currentDisplayConfiguration = getMonitorSizes();
|
||||
String settingsDisplayConfiguration = settings.displayConfiguration.get();
|
||||
boolean configurationHasChanged = !settingsDisplayConfiguration.equals(currentDisplayConfiguration);
|
||||
if (configurationHasChanged) settings.displayConfiguration.set(currentDisplayConfiguration);
|
||||
return configurationHasChanged;
|
||||
private boolean isWithinDisplayBounds() {
|
||||
// (x1, y1) is the top left corner of the window, (x2, y2) is the bottom right corner
|
||||
final double slack = 10;
|
||||
final double width = window.getWidth() - 2 * slack;
|
||||
final double height = window.getHeight() - 2 * slack;
|
||||
final double x1 = window.getX() + slack;
|
||||
final double y1 = window.getY() + slack;
|
||||
final double x2 = x1 + width;
|
||||
final double y2 = y1 + height;
|
||||
|
||||
final ObservableList<Screen> screens = Screen.getScreensForRectangle(x1, y1, width, height);
|
||||
|
||||
// Find the total visible area of the window
|
||||
double visibleArea = 0;
|
||||
for (Screen screen : screens) {
|
||||
Rectangle2D bounds = screen.getVisualBounds();
|
||||
|
||||
double xOverlap = Math.min(x2, bounds.getMaxX()) - Math.max(x1, bounds.getMinX());
|
||||
double yOverlap = Math.min(y2, bounds.getMaxY()) - Math.max(y1, bounds.getMinY());
|
||||
|
||||
visibleArea += xOverlap * yOverlap;
|
||||
}
|
||||
|
||||
final double windowArea = width * height;
|
||||
|
||||
// Within bounds if the visible area matches the window area
|
||||
return visibleArea == windowArea;
|
||||
}
|
||||
|
||||
private String getMonitorSizes() {
|
||||
ObservableList<Screen> screens = Screen.getScreens();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < screens.size(); i++) {
|
||||
Rectangle2D screenBounds = screens.get(i).getBounds();
|
||||
if (!sb.isEmpty()) sb.append(" ");
|
||||
sb.append("displayId: " + i + ", " + screenBounds.getWidth() + "x" + screenBounds.getHeight() + ";");
|
||||
private void checkDisplayBounds(WindowEvent evt) {
|
||||
|
||||
// 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(settings.windowXPosition.get());
|
||||
window.setY(settings.windowYPosition.get());
|
||||
window.setWidth(settings.windowWidth.get());
|
||||
window.setHeight(settings.windowHeight.get());
|
||||
}
|
||||
|
||||
if (!isWithinDisplayBounds()) {
|
||||
// If the position is illegal, then the window appears on the main screen in the middle of the window.
|
||||
Rectangle2D primaryScreenBounds = Screen.getPrimary().getBounds();
|
||||
window.setX((primaryScreenBounds.getWidth() - window.getMinWidth()) / 2);
|
||||
window.setY((primaryScreenBounds.getHeight() - window.getMinHeight()) / 2);
|
||||
window.setWidth(window.getMinWidth());
|
||||
window.setHeight(window.getMinHeight());
|
||||
savePositionalSettings();
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private void startResize(MouseEvent evt) {
|
||||
@@ -183,5 +205,4 @@ public class ResizeController implements FxController {
|
||||
public boolean isShowResizingArrows() {
|
||||
return showResizingArrows.get();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -20,7 +20,9 @@ import javafx.beans.property.SimpleBooleanProperty;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
import javafx.collections.ListChangeListener;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.event.Event;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.ListView;
|
||||
import javafx.scene.input.ContextMenuEvent;
|
||||
import javafx.scene.input.DragEvent;
|
||||
@@ -34,6 +36,7 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.EnumSet;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -59,12 +62,21 @@ public class VaultListController implements FxController {
|
||||
private final RemoveVaultComponent.Builder removeVaultDialogue;
|
||||
private final VaultListManager vaultListManager;
|
||||
private final BooleanProperty draggingVaultOver = new SimpleBooleanProperty();
|
||||
private final ResourceBundle resourceBundle;
|
||||
|
||||
public ListView<Vault> vaultList;
|
||||
public StackPane root;
|
||||
public Button addVaultBtn;
|
||||
|
||||
@Inject
|
||||
VaultListController(@MainWindow Stage mainWindow, ObservableList<Vault> vaults, ObjectProperty<Vault> selectedVault, VaultListCellFactory cellFactory, AddVaultWizardComponent.Builder addVaultWizard, RemoveVaultComponent.Builder removeVaultDialogue, VaultListManager vaultListManager) {
|
||||
VaultListController(@MainWindow Stage mainWindow, //
|
||||
ObservableList<Vault> vaults, //
|
||||
ObjectProperty<Vault> selectedVault, //
|
||||
VaultListCellFactory cellFactory, //
|
||||
AddVaultWizardComponent.Builder addVaultWizard, //
|
||||
RemoveVaultComponent.Builder removeVaultDialogue, //
|
||||
VaultListManager vaultListManager, //
|
||||
ResourceBundle resourceBundle) {
|
||||
this.mainWindow = mainWindow;
|
||||
this.vaults = vaults;
|
||||
this.selectedVault = selectedVault;
|
||||
@@ -72,6 +84,7 @@ public class VaultListController implements FxController {
|
||||
this.addVaultWizard = addVaultWizard;
|
||||
this.removeVaultDialogue = removeVaultDialogue;
|
||||
this.vaultListManager = vaultListManager;
|
||||
this.resourceBundle = resourceBundle;
|
||||
|
||||
this.emptyVaultList = Bindings.isEmpty(vaults);
|
||||
|
||||
@@ -127,6 +140,15 @@ public class VaultListController implements FxController {
|
||||
root.setOnDragOver(this::handleDragEvent);
|
||||
root.setOnDragDropped(this::handleDragEvent);
|
||||
root.setOnDragExited(this::handleDragEvent);
|
||||
|
||||
addVaultBtn.addEventFilter(ContextMenuEvent.CONTEXT_MENU_REQUESTED, Event::consume);
|
||||
}
|
||||
|
||||
@FXML
|
||||
private void showMenu() {
|
||||
double screenX = addVaultBtn.localToScreen(addVaultBtn.getBoundsInLocal()).getMinX();
|
||||
double screenY = addVaultBtn.localToScreen(addVaultBtn.getBoundsInLocal()).getMaxY();
|
||||
addVaultBtn.getContextMenu().show(addVaultBtn, screenX, screenY);
|
||||
}
|
||||
|
||||
private void deselect(MouseEvent released) {
|
||||
@@ -144,8 +166,13 @@ public class VaultListController implements FxController {
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void didClickAddVault() {
|
||||
addVaultWizard.build().showAddVaultWizard();
|
||||
public void didClickAddNewVault() {
|
||||
addVaultWizard.build().showAddNewVaultWizard(resourceBundle);
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void didClickAddExistingVault() {
|
||||
addVaultWizard.build().showAddExistingVaultWizard(resourceBundle);
|
||||
}
|
||||
|
||||
private void pressedShortcutToRemoveVault() {
|
||||
|
||||
@@ -795,6 +795,16 @@
|
||||
-fx-scale-shape: false;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* *
|
||||
* Add Vault - MenuItem *
|
||||
* *
|
||||
******************************************************************************/
|
||||
|
||||
.add-vault-menu-item {
|
||||
-fx-padding: 4px 8px;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* *
|
||||
* ProgressBar *
|
||||
|
||||
@@ -794,6 +794,16 @@
|
||||
-fx-scale-shape: false;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* *
|
||||
* Add Vault - MenuItem *
|
||||
* *
|
||||
******************************************************************************/
|
||||
|
||||
.add-vault-menu-item {
|
||||
-fx-padding: 4px 8px;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* *
|
||||
* ProgressBar *
|
||||
|
||||
@@ -24,9 +24,8 @@
|
||||
|
||||
<Region VBox.vgrow="ALWAYS"/>
|
||||
|
||||
<ButtonBar buttonMinWidth="120" buttonOrder="B+X">
|
||||
<ButtonBar buttonMinWidth="120" buttonOrder="+X">
|
||||
<buttons>
|
||||
<Button text="%generic.button.back" ButtonBar.buttonData="BACK_PREVIOUS" onAction="#back"/>
|
||||
<Button fx:id="finishButton" text="%addvaultwizard.existing.chooseBtn" ButtonBar.buttonData="NEXT_FORWARD" onAction="#chooseFileAndNext" defaultButton="true"/>
|
||||
</buttons>
|
||||
</ButtonBar>
|
||||
|
||||
@@ -68,9 +68,8 @@
|
||||
|
||||
<Region VBox.vgrow="ALWAYS"/>
|
||||
|
||||
<ButtonBar buttonMinWidth="120" buttonOrder="B+X">
|
||||
<ButtonBar buttonMinWidth="120" buttonOrder="+X">
|
||||
<buttons>
|
||||
<Button text="%generic.button.back" ButtonBar.buttonData="BACK_PREVIOUS" onAction="#back"/>
|
||||
<Button text="%generic.button.next" ButtonBar.buttonData="NEXT_FORWARD" onAction="#next" defaultButton="true" disable="${!controller.validVaultName}"/>
|
||||
</buttons>
|
||||
</ButtonBar>
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import org.cryptomator.ui.controls.FontAwesome5IconView?>
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.control.Button?>
|
||||
<?import javafx.scene.image.Image?>
|
||||
<?import javafx.scene.image.ImageView?>
|
||||
<?import javafx.scene.layout.Region?>
|
||||
<?import javafx.scene.layout.VBox?>
|
||||
<VBox xmlns:fx="http://javafx.com/fxml"
|
||||
xmlns="http://javafx.com/javafx"
|
||||
fx:controller="org.cryptomator.ui.addvaultwizard.AddVaultWelcomeController"
|
||||
prefWidth="450"
|
||||
prefHeight="450"
|
||||
spacing="12"
|
||||
alignment="TOP_CENTER">
|
||||
<padding>
|
||||
<Insets topRightBottomLeft="24"/>
|
||||
</padding>
|
||||
<children>
|
||||
<Region VBox.vgrow="ALWAYS"/>
|
||||
|
||||
<ImageView VBox.vgrow="ALWAYS" fitHeight="128" preserveRatio="true" smooth="true" cache="true">
|
||||
<Image url="@../img/logo.png"/>
|
||||
</ImageView>
|
||||
|
||||
<Region VBox.vgrow="ALWAYS"/>
|
||||
|
||||
<VBox alignment="CENTER" spacing="9">
|
||||
<Button styleClass="button-large" text="%addvaultwizard.welcome.newButton" onAction="#createNewVault" prefWidth="Infinity">
|
||||
<graphic>
|
||||
<FontAwesome5IconView glyph="MAGIC" glyphSize="15"/>
|
||||
</graphic>
|
||||
</Button>
|
||||
<Button styleClass="button-large" text="%addvaultwizard.welcome.existingButton" onAction="#chooseExistingVault" prefWidth="Infinity">
|
||||
<graphic>
|
||||
<FontAwesome5IconView glyph="FOLDER_OPEN" glyphSize="15"/>
|
||||
</graphic>
|
||||
</Button>
|
||||
</VBox>
|
||||
|
||||
<Region VBox.vgrow="ALWAYS"/>
|
||||
</children>
|
||||
</VBox>
|
||||
@@ -8,6 +8,8 @@
|
||||
<?import javafx.scene.layout.StackPane?>
|
||||
<?import javafx.scene.layout.VBox?>
|
||||
<?import javafx.scene.shape.Arc?>
|
||||
<?import javafx.scene.control.ContextMenu?>
|
||||
<?import javafx.scene.control.MenuItem?>
|
||||
<StackPane xmlns:fx="http://javafx.com/fxml"
|
||||
xmlns="http://javafx.com/javafx"
|
||||
fx:id="root"
|
||||
@@ -26,10 +28,26 @@
|
||||
<Arc VBox.vgrow="NEVER" styleClass="onboarding-overlay-arc" type="OPEN" centerX="50" centerY="0" radiusY="100" radiusX="50" startAngle="0" length="-60" strokeWidth="1"/>
|
||||
</VBox>
|
||||
</StackPane>
|
||||
<Button styleClass="toolbar-button" text="%main.vaultlist.addVaultBtn" onAction="#didClickAddVault" alignment="BASELINE_CENTER" maxWidth="Infinity">
|
||||
<Button fx:id="addVaultBtn" onAction="#showMenu" styleClass="toolbar-button" text="%main.vaultlist.addVaultBtn" alignment="BASELINE_CENTER" maxWidth="Infinity" contentDisplay="RIGHT">
|
||||
<graphic>
|
||||
<FontAwesome5IconView glyph="PLUS"/>
|
||||
<FontAwesome5IconView glyph="CARET_DOWN"/>
|
||||
</graphic>
|
||||
<contextMenu>
|
||||
<ContextMenu>
|
||||
<items>
|
||||
<MenuItem styleClass="add-vault-menu-item" text="%main.vaultlist.addVaultBtn.menuItemNew" onAction="#didClickAddNewVault" >
|
||||
<graphic>
|
||||
<FontAwesome5IconView glyph="PLUS" textAlignment="CENTER" wrappingWidth="14" />
|
||||
</graphic>
|
||||
</MenuItem>
|
||||
<MenuItem styleClass="add-vault-menu-item" text="%main.vaultlist.addVaultBtn.menuItemExisting" onAction="#didClickAddExistingVault" >
|
||||
<graphic>
|
||||
<FontAwesome5IconView glyph="FOLDER_OPEN" textAlignment="CENTER" wrappingWidth="14" />
|
||||
</graphic>
|
||||
</MenuItem>
|
||||
</items>
|
||||
</ContextMenu>
|
||||
</contextMenu>
|
||||
</Button>
|
||||
</VBox>
|
||||
<Region styleClass="drag-n-drop-border" visible="${controller.draggingVaultOver}"/>
|
||||
|
||||
@@ -41,10 +41,8 @@ traymenu.vault.reveal=Reveal
|
||||
|
||||
# Add Vault Wizard
|
||||
addvaultwizard.title=Add Vault
|
||||
## Welcome
|
||||
addvaultwizard.welcome.newButton=Create New Vault
|
||||
addvaultwizard.welcome.existingButton=Open Existing Vault
|
||||
## New
|
||||
addvaultwizard.new.title=Add New Vault
|
||||
### Name
|
||||
addvaultwizard.new.nameInstruction=Choose a name for the vault
|
||||
addvaultwizard.new.namePrompt=Vault Name
|
||||
@@ -94,6 +92,7 @@ addvault.new.readme.accessLocation.2=This is your vault's access location.
|
||||
addvault.new.readme.accessLocation.3=Any files added to this volume will be encrypted by Cryptomator. You can work on it like on any other drive/folder. This is only a decrypted view of its content, your files stay encrypted on your hard drive all the time.
|
||||
addvault.new.readme.accessLocation.4=Feel free to remove this file.
|
||||
## Existing
|
||||
addvaultwizard.existing.title=Add Existing Vault
|
||||
addvaultwizard.existing.instruction=Choose the "vault.cryptomator" file of your existing vault. If only a file named "masterkey.cryptomator" exists, select that instead.
|
||||
addvaultwizard.existing.chooseBtn=Choose…
|
||||
addvaultwizard.existing.filePickerTitle=Select Vault File
|
||||
@@ -139,7 +138,7 @@ unlock.error.customPath.message=Unable to mount vault to custom path
|
||||
unlock.error.customPath.description.notSupported=If you wish to keep using the custom path, please go to the preferences and select a volume type that supports it. Otherwise, go to the vault options and choose a supported mount point.
|
||||
unlock.error.customPath.description.notExists=The custom mount path does not exist. Either create it in your local filesystem or change it in the vault options.
|
||||
unlock.error.customPath.description.inUse=The drive letter or custom mount path "%s" is already in use.
|
||||
unlock.error.customPath.description.hideawayNotDir=The temporary, hidden file "%3$s" used for unlock could not be removed. Please check the file and then delete it manually.
|
||||
unlock.error.customPath.description.hideawayNotDir=The temporary, hidden file "%3$s" used for unlocking could not be removed. Please check the file and then delete it manually.
|
||||
unlock.error.customPath.description.couldNotBeCleaned=Your vault could not be mounted to the path "%s". Please try again or choose a different path.
|
||||
unlock.error.customPath.description.notEmptyDir=The custom mount path "%s" is not an empty folder. Please choose an empty folder and try again.
|
||||
unlock.error.customPath.description.generic=You have selected a custom mount path for this vault, but using it failed with the message: %2$s
|
||||
@@ -367,7 +366,9 @@ main.vaultlist.contextMenu.unlock=Unlock…
|
||||
main.vaultlist.contextMenu.unlockNow=Unlock Now
|
||||
main.vaultlist.contextMenu.vaultoptions=Show Vault Options
|
||||
main.vaultlist.contextMenu.reveal=Reveal Drive
|
||||
main.vaultlist.addVaultBtn=Add Vault
|
||||
main.vaultlist.addVaultBtn=Add
|
||||
main.vaultlist.addVaultBtn.menuItemNew=New Vault...
|
||||
main.vaultlist.addVaultBtn.menuItemExisting=Existing Vault...
|
||||
## Vault Detail
|
||||
### Welcome
|
||||
main.vaultDetail.welcomeOnboarding=Thanks for choosing Cryptomator to protect your files. If you need any assistance, check out our getting started guides:
|
||||
|
||||
Reference in New Issue
Block a user