mirror of
https://github.com/cryptomator/cryptomator.git
synced 2026-09-20 15:04:23 +00:00
Vastly refactored settings, integrated new webdav-nio-adapter snapshot version, allow reconfiguration of IPv6 and Port settings during runtime
This commit is contained in:
@@ -8,6 +8,7 @@
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.cryptomator.ui;
|
package org.cryptomator.ui;
|
||||||
|
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
@@ -22,12 +23,14 @@ import org.cryptomator.keychain.KeychainModule;
|
|||||||
import org.cryptomator.ui.settings.Settings;
|
import org.cryptomator.ui.settings.Settings;
|
||||||
import org.cryptomator.ui.settings.SettingsProvider;
|
import org.cryptomator.ui.settings.SettingsProvider;
|
||||||
import org.cryptomator.ui.util.DeferredCloser;
|
import org.cryptomator.ui.util.DeferredCloser;
|
||||||
|
import org.fxmisc.easybind.EasyBind;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import dagger.Module;
|
import dagger.Module;
|
||||||
import dagger.Provides;
|
import dagger.Provides;
|
||||||
import javafx.application.Application;
|
import javafx.application.Application;
|
||||||
|
import javafx.beans.binding.Binding;
|
||||||
import javafx.stage.Stage;
|
import javafx.stage.Stage;
|
||||||
|
|
||||||
@Module(includes = {CommonsModule.class, KeychainModule.class, JniModule.class, CryptoLibModule.class})
|
@Module(includes = {CommonsModule.class, KeychainModule.class, JniModule.class, CryptoLibModule.class})
|
||||||
@@ -83,8 +86,20 @@ class CryptomatorModule {
|
|||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
WebDavServer provideWebDavServer(Settings settings) {
|
Binding<InetSocketAddress> provideServerSocketAddressBinding(Settings settings) {
|
||||||
return WebDavServer.create("localhost", settings.getPort());
|
return EasyBind.combine(settings.useIpv6(), settings.port(), (useIpv6, port) -> {
|
||||||
|
String host = useIpv6 ? "::1" : "localhost";
|
||||||
|
return InetSocketAddress.createUnresolved(host, port.intValue());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
WebDavServer provideWebDavServer(Binding<InetSocketAddress> serverSocketAddressBinding) {
|
||||||
|
WebDavServer server = WebDavServer.create();
|
||||||
|
// no need to unsubscribe eventually, because server is a singleton
|
||||||
|
EasyBind.subscribe(serverSocketAddressBinding, server::bind);
|
||||||
|
return server;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,8 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2017 Skymatic UG (haftungsbeschränkt).
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the accompanying LICENSE file.
|
||||||
|
*******************************************************************************/
|
||||||
package org.cryptomator.ui;
|
package org.cryptomator.ui;
|
||||||
|
|
||||||
import static java.util.Arrays.asList;
|
import static java.util.Arrays.asList;
|
||||||
@@ -36,7 +41,7 @@ public class DebugMode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void initialize() {
|
public void initialize() {
|
||||||
if (settings.getDebugMode()) {
|
if (settings.debugMode().get()) {
|
||||||
enable();
|
enable();
|
||||||
LOG.debug("Debug mode initialized");
|
LOG.debug("Debug mode initialized");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -147,11 +147,11 @@ class ExitUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void showTrayNotification(TrayIcon trayIcon) {
|
private void showTrayNotification(TrayIcon trayIcon) {
|
||||||
if (settings.getNumTrayNotifications() <= 0) {
|
int remainingTrayNotification = settings.numTrayNotifications().get();
|
||||||
|
if (remainingTrayNotification <= 0) {
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
settings.setNumTrayNotifications(settings.getNumTrayNotifications() - 1);
|
settings.numTrayNotifications().set(remainingTrayNotification - 1);
|
||||||
settings.save();
|
|
||||||
}
|
}
|
||||||
final Runnable notificationCmd;
|
final Runnable notificationCmd;
|
||||||
if (SystemUtils.IS_OS_MAC_OSX) {
|
if (SystemUtils.IS_OS_MAC_OSX) {
|
||||||
|
|||||||
@@ -1,3 +1,8 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2017 Skymatic UG (haftungsbeschränkt).
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the accompanying LICENSE file.
|
||||||
|
*******************************************************************************/
|
||||||
package org.cryptomator.ui.controllers;
|
package org.cryptomator.ui.controllers;
|
||||||
|
|
||||||
import org.cryptomator.ui.settings.Localization;
|
import org.cryptomator.ui.settings.Localization;
|
||||||
|
|||||||
@@ -232,7 +232,7 @@ public class MainController extends LocalizedFXMLViewController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final VaultSettings vaultSettings = VaultSettings.withRandomId();
|
final VaultSettings vaultSettings = VaultSettings.withRandomId();
|
||||||
vaultSettings.setPath(vaultPath);
|
vaultSettings.path().set(vaultPath);
|
||||||
final Vault vault = vaultFactoy.get(vaultSettings);
|
final Vault vault = vaultFactoy.get(vaultSettings);
|
||||||
if (!vaults.contains(vault)) {
|
if (!vaults.contains(vault)) {
|
||||||
vaults.add(vault);
|
vaults.add(vault);
|
||||||
|
|||||||
@@ -1,3 +1,8 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2017 Skymatic UG (haftungsbeschränkt).
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the accompanying LICENSE file.
|
||||||
|
*******************************************************************************/
|
||||||
package org.cryptomator.ui.controllers;
|
package org.cryptomator.ui.controllers;
|
||||||
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
|||||||
@@ -18,9 +18,11 @@ import org.apache.commons.lang3.CharUtils;
|
|||||||
import org.apache.commons.lang3.SystemUtils;
|
import org.apache.commons.lang3.SystemUtils;
|
||||||
import org.cryptomator.ui.settings.Localization;
|
import org.cryptomator.ui.settings.Localization;
|
||||||
import org.cryptomator.ui.settings.Settings;
|
import org.cryptomator.ui.settings.Settings;
|
||||||
import org.fxmisc.easybind.EasyBind;
|
|
||||||
|
|
||||||
|
import javafx.beans.binding.Bindings;
|
||||||
|
import javafx.event.ActionEvent;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
|
import javafx.scene.control.Button;
|
||||||
import javafx.scene.control.CheckBox;
|
import javafx.scene.control.CheckBox;
|
||||||
import javafx.scene.control.ChoiceBox;
|
import javafx.scene.control.ChoiceBox;
|
||||||
import javafx.scene.control.Label;
|
import javafx.scene.control.Label;
|
||||||
@@ -44,6 +46,9 @@ public class SettingsController extends LocalizedFXMLViewController {
|
|||||||
@FXML
|
@FXML
|
||||||
private TextField portField;
|
private TextField portField;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private Button changePortButton;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private Label useIpv6Label;
|
private Label useIpv6Label;
|
||||||
|
|
||||||
@@ -65,25 +70,26 @@ public class SettingsController extends LocalizedFXMLViewController {
|
|||||||
@Override
|
@Override
|
||||||
public void initialize() {
|
public void initialize() {
|
||||||
checkForUpdatesCheckbox.setDisable(areUpdatesManagedExternally());
|
checkForUpdatesCheckbox.setDisable(areUpdatesManagedExternally());
|
||||||
checkForUpdatesCheckbox.setSelected(settings.isCheckForUpdatesEnabled() && !areUpdatesManagedExternally());
|
checkForUpdatesCheckbox.setSelected(settings.checkForUpdates().get() && !areUpdatesManagedExternally());
|
||||||
portField.setText(String.valueOf(settings.getPort()));
|
portField.setText(String.valueOf(settings.port().intValue()));
|
||||||
portField.addEventFilter(KeyEvent.KEY_TYPED, this::filterNumericKeyEvents);
|
portField.addEventFilter(KeyEvent.KEY_TYPED, this::filterNumericKeyEvents);
|
||||||
|
changePortButton.visibleProperty().bind(settings.port().asString().isNotEqualTo(portField.textProperty()));
|
||||||
|
changePortButton.disableProperty().bind(Bindings.createBooleanBinding(this::isPortValid, portField.textProperty()).not());
|
||||||
useIpv6Label.setVisible(SystemUtils.IS_OS_WINDOWS);
|
useIpv6Label.setVisible(SystemUtils.IS_OS_WINDOWS);
|
||||||
useIpv6Checkbox.setVisible(SystemUtils.IS_OS_WINDOWS);
|
useIpv6Checkbox.setVisible(SystemUtils.IS_OS_WINDOWS);
|
||||||
useIpv6Checkbox.setSelected(SystemUtils.IS_OS_WINDOWS && settings.shouldUseIpv6());
|
useIpv6Checkbox.setSelected(SystemUtils.IS_OS_WINDOWS && settings.useIpv6().get());
|
||||||
versionLabel.setText(String.format(localization.getString("settings.version.label"), applicationVersion().orElse("SNAPSHOT")));
|
versionLabel.setText(String.format(localization.getString("settings.version.label"), applicationVersion().orElse("SNAPSHOT")));
|
||||||
prefGvfsSchemeLabel.setVisible(SystemUtils.IS_OS_LINUX);
|
prefGvfsSchemeLabel.setVisible(SystemUtils.IS_OS_LINUX);
|
||||||
prefGvfsScheme.setVisible(SystemUtils.IS_OS_LINUX);
|
prefGvfsScheme.setVisible(SystemUtils.IS_OS_LINUX);
|
||||||
prefGvfsScheme.getItems().add("dav");
|
prefGvfsScheme.getItems().add("dav");
|
||||||
prefGvfsScheme.getItems().add("webdav");
|
prefGvfsScheme.getItems().add("webdav");
|
||||||
prefGvfsScheme.setValue(settings.getPreferredGvfsScheme());
|
prefGvfsScheme.setValue(settings.preferredGvfsScheme().get());
|
||||||
debugModeCheckbox.setSelected(settings.getDebugMode());
|
debugModeCheckbox.setSelected(settings.debugMode().get());
|
||||||
|
|
||||||
EasyBind.subscribe(checkForUpdatesCheckbox.selectedProperty(), this::checkForUpdateDidChange);
|
settings.checkForUpdates().bind(checkForUpdatesCheckbox.selectedProperty());
|
||||||
EasyBind.subscribe(portField.textProperty(), this::portDidChange);
|
settings.useIpv6().bind(useIpv6Checkbox.selectedProperty());
|
||||||
EasyBind.subscribe(useIpv6Checkbox.selectedProperty(), this::useIpv6DidChange);
|
settings.preferredGvfsScheme().bind(prefGvfsScheme.valueProperty());
|
||||||
EasyBind.subscribe(prefGvfsScheme.valueProperty(), this::prefGvfsSchemeDidChange);
|
settings.debugMode().bind(debugModeCheckbox.selectedProperty());
|
||||||
EasyBind.subscribe(debugModeCheckbox.selectedProperty(), this::debugModeDidChange);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -95,40 +101,30 @@ public class SettingsController extends LocalizedFXMLViewController {
|
|||||||
return Optional.ofNullable(getClass().getPackage().getImplementationVersion());
|
return Optional.ofNullable(getClass().getPackage().getImplementationVersion());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkForUpdateDidChange(Boolean newValue) {
|
@FXML
|
||||||
settings.setCheckForUpdatesEnabled(newValue);
|
private void changePort(ActionEvent evt) {
|
||||||
settings.save();
|
assert isPortValid() : "Button must be disabled, if port is invalid.";
|
||||||
|
try {
|
||||||
|
int port = Integer.parseInt(portField.getText());
|
||||||
|
settings.port().set(port);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
throw new IllegalStateException("Button must be disabled, if port is invalid.", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void portDidChange(String newValue) {
|
private boolean isPortValid() {
|
||||||
try {
|
try {
|
||||||
int port = Integer.parseInt(newValue);
|
int port = Integer.parseInt(portField.getText());
|
||||||
if (!settings.isPortValid(port)) {
|
if (port == 0 || port >= Settings.MIN_PORT && port <= Settings.MAX_PORT) {
|
||||||
settings.setPort(Settings.DEFAULT_PORT);
|
return true;
|
||||||
} else {
|
} else {
|
||||||
settings.setPort(port);
|
return false;
|
||||||
settings.save();
|
|
||||||
}
|
}
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
portField.setText(String.valueOf(Settings.DEFAULT_PORT));
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void useIpv6DidChange(Boolean newValue) {
|
|
||||||
settings.setUseIpv6(newValue);
|
|
||||||
settings.save();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void debugModeDidChange(Boolean newValue) {
|
|
||||||
settings.setDebugMode(newValue);
|
|
||||||
settings.save();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void prefGvfsSchemeDidChange(String newValue) {
|
|
||||||
settings.setPreferredGvfsScheme(newValue);
|
|
||||||
settings.save();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void filterNumericKeyEvents(KeyEvent t) {
|
private void filterNumericKeyEvents(KeyEvent t) {
|
||||||
if (t.getCharacter() == null || t.getCharacter().length() == 0) {
|
if (t.getCharacter() == null || t.getCharacter().length() == 0) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -1,3 +1,8 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2017 Skymatic UG (haftungsbeschränkt).
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the accompanying LICENSE file.
|
||||||
|
*******************************************************************************/
|
||||||
package org.cryptomator.ui.controllers;
|
package org.cryptomator.ui.controllers;
|
||||||
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ public class WelcomeController extends LocalizedFXMLViewController {
|
|||||||
public void initialize() {
|
public void initialize() {
|
||||||
if (areUpdatesManagedExternally()) {
|
if (areUpdatesManagedExternally()) {
|
||||||
checkForUpdatesContainer.setVisible(false);
|
checkForUpdatesContainer.setVisible(false);
|
||||||
} else if (settings.isCheckForUpdatesEnabled()) {
|
} else if (settings.checkForUpdates().get()) {
|
||||||
this.checkForUpdates();
|
this.checkForUpdates();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,8 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2017 Skymatic UG (haftungsbeschränkt).
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the accompanying LICENSE file.
|
||||||
|
*******************************************************************************/
|
||||||
package org.cryptomator.ui.model;
|
package org.cryptomator.ui.model;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|||||||
@@ -1,3 +1,8 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2017 Skymatic UG (haftungsbeschränkt).
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the accompanying LICENSE file.
|
||||||
|
*******************************************************************************/
|
||||||
package org.cryptomator.ui.model;
|
package org.cryptomator.ui.model;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|||||||
+6
-1
@@ -1,3 +1,8 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2017 Skymatic UG (haftungsbeschränkt).
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the accompanying LICENSE file.
|
||||||
|
*******************************************************************************/
|
||||||
package org.cryptomator.ui.model;
|
package org.cryptomator.ui.model;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -60,7 +65,7 @@ class UpgradeVersion3DropBundleExtension extends UpgradeStrategy {
|
|||||||
LOG.info("Renaming {} to {}", path, newPath.getFileName());
|
LOG.info("Renaming {} to {}", path, newPath.getFileName());
|
||||||
Files.move(path, path.resolveSibling(newVaultName));
|
Files.move(path, path.resolveSibling(newVaultName));
|
||||||
Platform.runLater(() -> {
|
Platform.runLater(() -> {
|
||||||
vault.getVaultSettings().setPath(newPath);
|
vault.getVaultSettings().path().set(newPath);
|
||||||
settings.save();
|
settings.save();
|
||||||
});
|
});
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
|||||||
@@ -1,3 +1,8 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2017 Skymatic UG (haftungsbeschränkt).
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the accompanying LICENSE file.
|
||||||
|
*******************************************************************************/
|
||||||
package org.cryptomator.ui.model;
|
package org.cryptomator.ui.model;
|
||||||
|
|
||||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
|
|||||||
@@ -1,3 +1,8 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2017 Skymatic UG (haftungsbeschränkt).
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the accompanying LICENSE file.
|
||||||
|
*******************************************************************************/
|
||||||
package org.cryptomator.ui.model;
|
package org.cryptomator.ui.model;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ public class Vault {
|
|||||||
if (!server.isRunning()) {
|
if (!server.isRunning()) {
|
||||||
server.start();
|
server.start();
|
||||||
}
|
}
|
||||||
servlet = server.createWebDavServlet(fs.getPath("/"), vaultSettings.getId() + "/" + vaultSettings.getMountName());
|
servlet = server.createWebDavServlet(fs.getPath("/"), vaultSettings.getId() + "/" + vaultSettings.mountName().get());
|
||||||
servlet.start();
|
servlet.start();
|
||||||
unlockSuccess = true;
|
unlockSuccess = true;
|
||||||
|
|
||||||
@@ -167,17 +167,16 @@ public class Vault {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String getWebDavUrl() {
|
public String getWebDavUrl() {
|
||||||
// TODO implement
|
return servlet.getServletRootUri().toString();
|
||||||
return "http://localhost/not/implemented";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Path getPath() {
|
public Path getPath() {
|
||||||
return vaultSettings.pathProperty().getValue();
|
return vaultSettings.path().getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Binding<String> displayablePath() {
|
public Binding<String> displayablePath() {
|
||||||
Path homeDir = Paths.get(SystemUtils.USER_HOME);
|
Path homeDir = Paths.get(SystemUtils.USER_HOME);
|
||||||
return EasyBind.map(vaultSettings.pathProperty(), p -> {
|
return EasyBind.map(vaultSettings.path(), p -> {
|
||||||
if (p.startsWith(homeDir)) {
|
if (p.startsWith(homeDir)) {
|
||||||
Path relativePath = homeDir.relativize(p);
|
Path relativePath = homeDir.relativize(p);
|
||||||
String homePrefix = SystemUtils.IS_OS_WINDOWS ? "~\\" : "~/";
|
String homePrefix = SystemUtils.IS_OS_WINDOWS ? "~\\" : "~/";
|
||||||
@@ -192,7 +191,7 @@ public class Vault {
|
|||||||
* @return Directory name without preceeding path components and file extension
|
* @return Directory name without preceeding path components and file extension
|
||||||
*/
|
*/
|
||||||
public Binding<String> name() {
|
public Binding<String> name() {
|
||||||
return EasyBind.map(vaultSettings.pathProperty(), Path::getFileName).map(Path::toString);
|
return EasyBind.map(vaultSettings.path(), Path::getFileName).map(Path::toString);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean doesVaultDirectoryExist() {
|
public boolean doesVaultDirectoryExist() {
|
||||||
@@ -238,30 +237,30 @@ public class Vault {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String getMountName() {
|
public String getMountName() {
|
||||||
return vaultSettings.getMountName();
|
return vaultSettings.mountName().get();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMountName(String mountName) throws IllegalArgumentException {
|
public void setMountName(String mountName) throws IllegalArgumentException {
|
||||||
if (StringUtils.isBlank(mountName)) {
|
if (StringUtils.isBlank(mountName)) {
|
||||||
throw new IllegalArgumentException("mount name is empty");
|
throw new IllegalArgumentException("mount name is empty");
|
||||||
} else {
|
} else {
|
||||||
vaultSettings.setMountName(mountName);
|
vaultSettings.mountName().set(VaultSettings.normalizeMountName(mountName));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Character getWinDriveLetter() {
|
public Character getWinDriveLetter() {
|
||||||
if (vaultSettings.getWinDriveLetter() == null) {
|
if (vaultSettings.winDriveLetter().get() == null) {
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
return vaultSettings.getWinDriveLetter().charAt(0);
|
return vaultSettings.winDriveLetter().get().charAt(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setWinDriveLetter(Character winDriveLetter) {
|
public void setWinDriveLetter(Character winDriveLetter) {
|
||||||
if (winDriveLetter == null) {
|
if (winDriveLetter == null) {
|
||||||
vaultSettings.setWinDriveLetter(null);
|
vaultSettings.winDriveLetter().set(null);
|
||||||
} else {
|
} else {
|
||||||
vaultSettings.setWinDriveLetter(String.valueOf(winDriveLetter));
|
vaultSettings.winDriveLetter().set(String.valueOf(winDriveLetter));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,8 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2017 Skymatic UG (haftungsbeschränkt).
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the accompanying LICENSE file.
|
||||||
|
*******************************************************************************/
|
||||||
package org.cryptomator.ui.model;
|
package org.cryptomator.ui.model;
|
||||||
|
|
||||||
import org.cryptomator.ui.model.VaultModule.PerVault;
|
import org.cryptomator.ui.model.VaultModule.PerVault;
|
||||||
|
|||||||
@@ -1,3 +1,8 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2017 Skymatic UG (haftungsbeschränkt).
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the accompanying LICENSE file.
|
||||||
|
*******************************************************************************/
|
||||||
package org.cryptomator.ui.model;
|
package org.cryptomator.ui.model;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -9,7 +14,6 @@ import javax.inject.Singleton;
|
|||||||
import org.cryptomator.ui.settings.Settings;
|
import org.cryptomator.ui.settings.Settings;
|
||||||
import org.cryptomator.ui.settings.VaultSettings;
|
import org.cryptomator.ui.settings.VaultSettings;
|
||||||
|
|
||||||
import javafx.collections.FXCollections;
|
|
||||||
import javafx.collections.ListChangeListener.Change;
|
import javafx.collections.ListChangeListener.Change;
|
||||||
import javafx.collections.ObservableList;
|
import javafx.collections.ObservableList;
|
||||||
import javafx.collections.transformation.TransformationList;
|
import javafx.collections.transformation.TransformationList;
|
||||||
@@ -22,14 +26,9 @@ public class VaultList extends TransformationList<Vault, VaultSettings> {
|
|||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public VaultList(Settings settings, VaultFactory vaultFactory) {
|
public VaultList(Settings settings, VaultFactory vaultFactory) {
|
||||||
this(FXCollections.observableList(settings.getDirectories()), settings, vaultFactory);
|
super(settings.getDirectories());
|
||||||
}
|
this.source = settings.getDirectories();
|
||||||
|
|
||||||
private VaultList(ObservableList<VaultSettings> source, Settings settings, VaultFactory vaultFactory) {
|
|
||||||
super(source);
|
|
||||||
this.source = source;
|
|
||||||
this.vaultFactory = vaultFactory;
|
this.vaultFactory = vaultFactory;
|
||||||
addListener((Change<? extends Vault> change) -> settings.save());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -1,3 +1,8 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2017 Skymatic UG (haftungsbeschränkt).
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the accompanying LICENSE file.
|
||||||
|
*******************************************************************************/
|
||||||
package org.cryptomator.ui.model;
|
package org.cryptomator.ui.model;
|
||||||
|
|
||||||
import java.lang.annotation.Documented;
|
import java.lang.annotation.Documented;
|
||||||
|
|||||||
@@ -1,3 +1,8 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2017 Skymatic UG (haftungsbeschränkt).
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the accompanying LICENSE file.
|
||||||
|
*******************************************************************************/
|
||||||
package org.cryptomator.ui.model;
|
package org.cryptomator.ui.model;
|
||||||
|
|
||||||
import java.nio.file.FileSystems;
|
import java.nio.file.FileSystems;
|
||||||
|
|||||||
@@ -1,3 +1,8 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2017 Skymatic UG (haftungsbeschränkt).
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the accompanying LICENSE file.
|
||||||
|
*******************************************************************************/
|
||||||
package org.cryptomator.ui.settings;
|
package org.cryptomator.ui.settings;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|||||||
@@ -8,58 +8,55 @@
|
|||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
package org.cryptomator.ui.settings;
|
package org.cryptomator.ui.settings;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import com.google.gson.annotations.Expose;
|
import javafx.beans.property.BooleanProperty;
|
||||||
import com.google.gson.annotations.SerializedName;
|
import javafx.beans.property.IntegerProperty;
|
||||||
|
import javafx.beans.property.SimpleBooleanProperty;
|
||||||
|
import javafx.beans.property.SimpleIntegerProperty;
|
||||||
|
import javafx.beans.property.SimpleStringProperty;
|
||||||
|
import javafx.beans.property.StringProperty;
|
||||||
|
import javafx.beans.value.ObservableValue;
|
||||||
|
import javafx.collections.FXCollections;
|
||||||
|
import javafx.collections.ListChangeListener;
|
||||||
|
import javafx.collections.ObservableList;
|
||||||
|
|
||||||
public class Settings {
|
public class Settings {
|
||||||
|
|
||||||
public static final int MIN_PORT = 1024;
|
public static final int MIN_PORT = 1024;
|
||||||
public static final int MAX_PORT = 65535;
|
public static final int MAX_PORT = 65535;
|
||||||
|
public static final boolean DEFAULT_CHECK_FOR_UDPATES = true;
|
||||||
public static final int DEFAULT_PORT = 42427;
|
public static final int DEFAULT_PORT = 42427;
|
||||||
public static final boolean DEFAULT_USE_IPV6 = false;
|
public static final boolean DEFAULT_USE_IPV6 = false;
|
||||||
public static final Integer DEFAULT_NUM_TRAY_NOTIFICATIONS = 3;
|
public static final int DEFAULT_NUM_TRAY_NOTIFICATIONS = 3;
|
||||||
public static final String DEFAULT_GVFS_SCHEME = "dav";
|
public static final String DEFAULT_GVFS_SCHEME = "dav";
|
||||||
public static final boolean DEFAULT_DEBUG_MODE = false;
|
public static final boolean DEFAULT_DEBUG_MODE = false;
|
||||||
|
|
||||||
private final Consumer<Settings> saveCmd;
|
private final Consumer<Settings> saveCmd;
|
||||||
|
private final ObservableList<VaultSettings> directories = FXCollections.observableArrayList();
|
||||||
@Expose
|
private final BooleanProperty checkForUpdates = new SimpleBooleanProperty(DEFAULT_CHECK_FOR_UDPATES);
|
||||||
@SerializedName("directories")
|
private final IntegerProperty port = new SimpleIntegerProperty(DEFAULT_PORT);
|
||||||
private List<VaultSettings> directories;
|
private final BooleanProperty useIpv6 = new SimpleBooleanProperty(DEFAULT_USE_IPV6);
|
||||||
|
private final IntegerProperty numTrayNotifications = new SimpleIntegerProperty(DEFAULT_NUM_TRAY_NOTIFICATIONS);
|
||||||
@Expose
|
private final StringProperty preferredGvfsScheme = new SimpleStringProperty(DEFAULT_GVFS_SCHEME);
|
||||||
@SerializedName("checkForUpdatesEnabled")
|
private final BooleanProperty debugMode = new SimpleBooleanProperty(DEFAULT_DEBUG_MODE);
|
||||||
private Boolean checkForUpdatesEnabled;
|
|
||||||
|
|
||||||
@Expose
|
|
||||||
@SerializedName("port")
|
|
||||||
private Integer port;
|
|
||||||
|
|
||||||
@Expose
|
|
||||||
@SerializedName("useIpv6")
|
|
||||||
private Boolean useIpv6;
|
|
||||||
|
|
||||||
@Expose
|
|
||||||
@SerializedName("numTrayNotifications")
|
|
||||||
private Integer numTrayNotifications;
|
|
||||||
|
|
||||||
@Expose
|
|
||||||
@SerializedName("preferredGvfsScheme")
|
|
||||||
private String preferredGvfsScheme;
|
|
||||||
|
|
||||||
@Expose
|
|
||||||
@SerializedName("debugMode")
|
|
||||||
private Boolean debugMode;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Package-private constructor; use {@link SettingsProvider}.
|
* Package-private constructor; use {@link SettingsProvider}.
|
||||||
*/
|
*/
|
||||||
Settings(Consumer<Settings> saveCmd) {
|
Settings(Consumer<Settings> saveCmd) {
|
||||||
this.saveCmd = saveCmd;
|
this.saveCmd = saveCmd;
|
||||||
|
directories.addListener((ListChangeListener.Change<? extends VaultSettings> change) -> this.save());
|
||||||
|
checkForUpdates.addListener(this::somethingChanged);
|
||||||
|
port.addListener(this::somethingChanged);
|
||||||
|
useIpv6.addListener(this::somethingChanged);
|
||||||
|
numTrayNotifications.addListener(this::somethingChanged);
|
||||||
|
preferredGvfsScheme.addListener(this::somethingChanged);
|
||||||
|
debugMode.addListener(this::somethingChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void somethingChanged(ObservableValue<?> observable, Object oldValue, Object newValue) {
|
||||||
|
this.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void save() {
|
public void save() {
|
||||||
@@ -70,75 +67,32 @@ public class Settings {
|
|||||||
|
|
||||||
/* Getter/Setter */
|
/* Getter/Setter */
|
||||||
|
|
||||||
public List<VaultSettings> getDirectories() {
|
public ObservableList<VaultSettings> getDirectories() {
|
||||||
if (directories == null) {
|
|
||||||
directories = new ArrayList<>();
|
|
||||||
}
|
|
||||||
return directories;
|
return directories;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDirectories(List<VaultSettings> directories) {
|
public BooleanProperty checkForUpdates() {
|
||||||
this.directories = directories;
|
return checkForUpdates;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isCheckForUpdatesEnabled() {
|
public IntegerProperty port() {
|
||||||
// not false meaning "null or true", so that true is the default value, if not setting exists yet.
|
|
||||||
return !Boolean.FALSE.equals(checkForUpdatesEnabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCheckForUpdatesEnabled(boolean checkForUpdatesEnabled) {
|
|
||||||
this.checkForUpdatesEnabled = checkForUpdatesEnabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPort(int port) {
|
|
||||||
if (!isPortValid(port)) {
|
|
||||||
throw new IllegalArgumentException("Invalid port");
|
|
||||||
}
|
|
||||||
this.port = port;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getPort() {
|
|
||||||
if (port == null || !isPortValid(port)) {
|
|
||||||
return DEFAULT_PORT;
|
|
||||||
} else {
|
|
||||||
return port;
|
return port;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BooleanProperty useIpv6() {
|
||||||
|
return useIpv6;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isPortValid(int port) {
|
public IntegerProperty numTrayNotifications() {
|
||||||
return port == DEFAULT_PORT || port >= MIN_PORT && port <= MAX_PORT || port == 0;
|
return numTrayNotifications;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean shouldUseIpv6() {
|
public StringProperty preferredGvfsScheme() {
|
||||||
return useIpv6 == null ? DEFAULT_USE_IPV6 : useIpv6;
|
return preferredGvfsScheme;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUseIpv6(boolean useIpv6) {
|
public BooleanProperty debugMode() {
|
||||||
this.useIpv6 = useIpv6;
|
return debugMode;
|
||||||
}
|
|
||||||
|
|
||||||
public Integer getNumTrayNotifications() {
|
|
||||||
return numTrayNotifications == null ? DEFAULT_NUM_TRAY_NOTIFICATIONS : numTrayNotifications;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setNumTrayNotifications(Integer numTrayNotifications) {
|
|
||||||
this.numTrayNotifications = numTrayNotifications;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getPreferredGvfsScheme() {
|
|
||||||
return preferredGvfsScheme == null ? DEFAULT_GVFS_SCHEME : preferredGvfsScheme;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPreferredGvfsScheme(String preferredGvfsScheme) {
|
|
||||||
this.preferredGvfsScheme = preferredGvfsScheme;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean getDebugMode() {
|
|
||||||
return debugMode == null ? DEFAULT_DEBUG_MODE : debugMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDebugMode(boolean debugMode) {
|
|
||||||
this.debugMode = debugMode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
package org.cryptomator.ui.settings;
|
|
||||||
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
import java.util.function.Consumer;
|
|
||||||
|
|
||||||
import com.google.gson.InstanceCreator;
|
|
||||||
|
|
||||||
class SettingsInstanceCreator implements InstanceCreator<Settings> {
|
|
||||||
|
|
||||||
private final Consumer<Settings> saveCmd;
|
|
||||||
|
|
||||||
public SettingsInstanceCreator(Consumer<Settings> saveCmd) {
|
|
||||||
this.saveCmd = saveCmd;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Settings createInstance(Type type) {
|
|
||||||
return new Settings(saveCmd);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,103 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2017 Skymatic UG (haftungsbeschränkt).
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the accompanying LICENSE file.
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.cryptomator.ui.settings;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import com.google.gson.TypeAdapter;
|
||||||
|
import com.google.gson.stream.JsonReader;
|
||||||
|
import com.google.gson.stream.JsonToken;
|
||||||
|
import com.google.gson.stream.JsonWriter;
|
||||||
|
|
||||||
|
public class SettingsJsonAdapter extends TypeAdapter<Settings> {
|
||||||
|
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(SettingsJsonAdapter.class);
|
||||||
|
|
||||||
|
private final Consumer<Settings> saveCmd;
|
||||||
|
private final VaultSettingsJsonAdapter vaultSettingsJsonAdapter = new VaultSettingsJsonAdapter();
|
||||||
|
|
||||||
|
public SettingsJsonAdapter(Consumer<Settings> saveCmd) {
|
||||||
|
this.saveCmd = saveCmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(JsonWriter out, Settings value) throws IOException {
|
||||||
|
out.beginObject();
|
||||||
|
out.name("directories");
|
||||||
|
writeVaultSettingsArray(out, value.getDirectories());
|
||||||
|
out.name("checkForUpdatesEnabled").value(value.checkForUpdates().get());
|
||||||
|
out.name("port").value(value.port().get());
|
||||||
|
out.name("useIpv6").value(value.useIpv6().get());
|
||||||
|
out.name("numTrayNotifications").value(value.numTrayNotifications().get());
|
||||||
|
out.name("preferredGvfsScheme").value(value.preferredGvfsScheme().get());
|
||||||
|
out.name("debugMode").value(value.debugMode().get());
|
||||||
|
out.endObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeVaultSettingsArray(JsonWriter out, Iterable<VaultSettings> vaultSettings) throws IOException {
|
||||||
|
out.beginArray();
|
||||||
|
for (VaultSettings value : vaultSettings) {
|
||||||
|
vaultSettingsJsonAdapter.write(out, value);
|
||||||
|
}
|
||||||
|
out.endArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Settings read(JsonReader in) throws IOException {
|
||||||
|
Settings settings = new Settings(saveCmd);
|
||||||
|
|
||||||
|
in.beginObject();
|
||||||
|
while (in.hasNext()) {
|
||||||
|
String name = in.nextName();
|
||||||
|
switch (name) {
|
||||||
|
case "directories":
|
||||||
|
settings.getDirectories().addAll(readVaultSettingsArray(in));
|
||||||
|
break;
|
||||||
|
case "checkForUpdatesEnabled":
|
||||||
|
settings.checkForUpdates().set(in.nextBoolean());
|
||||||
|
break;
|
||||||
|
case "port":
|
||||||
|
settings.port().set(in.nextInt());
|
||||||
|
break;
|
||||||
|
case "useIpv6":
|
||||||
|
settings.useIpv6().set(in.nextBoolean());
|
||||||
|
break;
|
||||||
|
case "numTrayNotifications":
|
||||||
|
settings.numTrayNotifications().set(in.nextInt());
|
||||||
|
break;
|
||||||
|
case "preferredGvfsScheme":
|
||||||
|
settings.preferredGvfsScheme().set(in.nextString());
|
||||||
|
break;
|
||||||
|
case "debugMode":
|
||||||
|
settings.debugMode().set(in.nextBoolean());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOG.warn("Unsupported vault setting found in JSON: " + name);
|
||||||
|
in.skipValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
in.endObject();
|
||||||
|
|
||||||
|
return settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<VaultSettings> readVaultSettingsArray(JsonReader in) throws IOException {
|
||||||
|
List<VaultSettings> result = new ArrayList<>();
|
||||||
|
in.beginArray();
|
||||||
|
while (!JsonToken.END_ARRAY.equals(in.peek())) {
|
||||||
|
result.add(vaultSettingsJsonAdapter.read(in));
|
||||||
|
}
|
||||||
|
in.endArray();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -21,7 +21,6 @@ import java.nio.file.FileSystems;
|
|||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.StandardOpenOption;
|
import java.nio.file.StandardOpenOption;
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
@@ -63,15 +62,15 @@ public class SettingsProvider implements Provider<Settings> {
|
|||||||
private final ScheduledExecutorService saveScheduler = Executors.newSingleThreadScheduledExecutor();
|
private final ScheduledExecutorService saveScheduler = Executors.newSingleThreadScheduledExecutor();
|
||||||
private final AtomicReference<ScheduledFuture<?>> scheduledSaveCmd = new AtomicReference<>();
|
private final AtomicReference<ScheduledFuture<?>> scheduledSaveCmd = new AtomicReference<>();
|
||||||
private final AtomicReference<Settings> settings = new AtomicReference<>();
|
private final AtomicReference<Settings> settings = new AtomicReference<>();
|
||||||
private final SettingsInstanceCreator settingsInstanceCreator = new SettingsInstanceCreator(this::scheduleSave);
|
private final SettingsJsonAdapter settingsJsonAdapter = new SettingsJsonAdapter(this::scheduleSave);
|
||||||
private final Gson gson;
|
private final Gson gson;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public SettingsProvider() {
|
public SettingsProvider() {
|
||||||
GsonBuilder gsonBuilder = new GsonBuilder() //
|
this.gson = new GsonBuilder() //
|
||||||
.setPrettyPrinting().setLenient().disableHtmlEscaping().excludeFieldsWithoutExposeAnnotation();
|
.setPrettyPrinting().setLenient().disableHtmlEscaping() //
|
||||||
gsonBuilder.registerTypeAdapter(Settings.class, settingsInstanceCreator);
|
.registerTypeAdapter(Settings.class, settingsJsonAdapter) //
|
||||||
this.gson = gsonBuilder.create();
|
.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Path getSettingsPath() {
|
private Path getSettingsPath() {
|
||||||
@@ -101,7 +100,7 @@ public class SettingsProvider implements Provider<Settings> {
|
|||||||
LOG.info("Settings loaded from " + settingsPath);
|
LOG.info("Settings loaded from " + settingsPath);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOG.info("Failed to load settings, creating new one.");
|
LOG.info("Failed to load settings, creating new one.");
|
||||||
settings = settingsInstanceCreator.createInstance(Settings.class);
|
settings = new Settings(this::scheduleSave);
|
||||||
}
|
}
|
||||||
return settings;
|
return settings;
|
||||||
}
|
}
|
||||||
@@ -120,7 +119,7 @@ public class SettingsProvider implements Provider<Settings> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void save(Settings settings) {
|
private void save(Settings settings) {
|
||||||
Objects.requireNonNull(settings);
|
assert settings != null : "method should only be invoked by #scheduleSave, which checks for null";
|
||||||
final Path settingsPath = getSettingsPath();
|
final Path settingsPath = getSettingsPath();
|
||||||
try {
|
try {
|
||||||
Files.createDirectories(settingsPath.getParent());
|
Files.createDirectories(settingsPath.getParent());
|
||||||
|
|||||||
@@ -1,3 +1,8 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2017 Skymatic UG (haftungsbeschränkt).
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the accompanying LICENSE file.
|
||||||
|
*******************************************************************************/
|
||||||
package org.cryptomator.ui.settings;
|
package org.cryptomator.ui.settings;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
@@ -8,23 +13,31 @@ import java.util.Objects;
|
|||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.fxmisc.easybind.EasyBind;
|
||||||
|
|
||||||
import com.google.gson.annotations.JsonAdapter;
|
import javafx.beans.property.ObjectProperty;
|
||||||
|
|
||||||
import javafx.beans.property.Property;
|
|
||||||
import javafx.beans.property.SimpleObjectProperty;
|
import javafx.beans.property.SimpleObjectProperty;
|
||||||
import javafx.beans.property.SimpleStringProperty;
|
import javafx.beans.property.SimpleStringProperty;
|
||||||
|
import javafx.beans.property.StringProperty;
|
||||||
|
|
||||||
@JsonAdapter(VaultSettingsJsonAdapter.class)
|
|
||||||
public class VaultSettings {
|
public class VaultSettings {
|
||||||
|
|
||||||
private final String id;
|
private final String id;
|
||||||
private final Property<Path> path = new SimpleObjectProperty<>();
|
private final ObjectProperty<Path> path = new SimpleObjectProperty<>();
|
||||||
private final Property<String> mountName = new SimpleStringProperty();
|
private final StringProperty mountName = new SimpleStringProperty();
|
||||||
private final Property<String> winDriveLetter = new SimpleStringProperty();
|
private final StringProperty winDriveLetter = new SimpleStringProperty();
|
||||||
|
|
||||||
public VaultSettings(String id) {
|
public VaultSettings(String id) {
|
||||||
this.id = Objects.requireNonNull(id);
|
this.id = Objects.requireNonNull(id);
|
||||||
|
|
||||||
|
EasyBind.subscribe(path, this::deriveMountNameFromPath);
|
||||||
|
// TODO: automatically save settings, when chaning vaultSettings
|
||||||
|
}
|
||||||
|
|
||||||
|
private void deriveMountNameFromPath(Path path) {
|
||||||
|
if (path != null && StringUtils.isBlank(mountName.get())) {
|
||||||
|
mountName.set(normalizeMountName(path.getFileName().toString()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static VaultSettings withRandomId() {
|
public static VaultSettings withRandomId() {
|
||||||
@@ -48,10 +61,7 @@ public class VaultSettings {
|
|||||||
return uuidBuffer.array();
|
return uuidBuffer.array();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
public static String normalizeMountName(String mountName) {
|
||||||
* visible for testing
|
|
||||||
*/
|
|
||||||
static String normalizeMountName(String mountName) {
|
|
||||||
String normalizedMountName = StringUtils.stripAccents(mountName);
|
String normalizedMountName = StringUtils.stripAccents(mountName);
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
for (char c : normalizedMountName.toCharArray()) {
|
for (char c : normalizedMountName.toCharArray()) {
|
||||||
@@ -76,43 +86,16 @@ public class VaultSettings {
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Property<Path> pathProperty() {
|
public ObjectProperty<Path> path() {
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Path getPath() {
|
public StringProperty mountName() {
|
||||||
return path.getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPath(Path path) {
|
|
||||||
this.path.setValue(path);
|
|
||||||
if (StringUtils.isBlank(getMountName())) {
|
|
||||||
setMountName(path.getFileName().toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Property<String> mountNameProperty() {
|
|
||||||
return mountName;
|
return mountName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getMountName() {
|
public StringProperty winDriveLetter() {
|
||||||
return mountName.getValue();
|
return winDriveLetter;
|
||||||
}
|
|
||||||
|
|
||||||
public void setMountName(String mountName) {
|
|
||||||
this.mountName.setValue(normalizeMountName(mountName));
|
|
||||||
}
|
|
||||||
|
|
||||||
public Property<String> winDriveLetterProperty() {
|
|
||||||
return mountName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getWinDriveLetter() {
|
|
||||||
return winDriveLetter.getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setWinDriveLetter(String winDriveLetter) {
|
|
||||||
this.winDriveLetter.setValue(winDriveLetter);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Hashcode/Equals */
|
/* Hashcode/Equals */
|
||||||
|
|||||||
@@ -1,3 +1,8 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2017 Skymatic UG (haftungsbeschränkt).
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the accompanying LICENSE file.
|
||||||
|
*******************************************************************************/
|
||||||
package org.cryptomator.ui.settings;
|
package org.cryptomator.ui.settings;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -18,9 +23,9 @@ class VaultSettingsJsonAdapter extends TypeAdapter<VaultSettings> {
|
|||||||
public void write(JsonWriter out, VaultSettings value) throws IOException {
|
public void write(JsonWriter out, VaultSettings value) throws IOException {
|
||||||
out.beginObject();
|
out.beginObject();
|
||||||
out.name("id").value(value.getId());
|
out.name("id").value(value.getId());
|
||||||
out.name("path").value(value.getPath().toString());
|
out.name("path").value(value.path().get().toString());
|
||||||
out.name("mountName").value(value.getMountName());
|
out.name("mountName").value(value.mountName().get());
|
||||||
out.name("winDriveLetter").value(value.getWinDriveLetter());
|
out.name("winDriveLetter").value(value.winDriveLetter().get());
|
||||||
out.endObject();
|
out.endObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,9 +60,9 @@ class VaultSettingsJsonAdapter extends TypeAdapter<VaultSettings> {
|
|||||||
in.endObject();
|
in.endObject();
|
||||||
|
|
||||||
VaultSettings settings = (id == null) ? VaultSettings.withRandomId() : new VaultSettings(id);
|
VaultSettings settings = (id == null) ? VaultSettings.withRandomId() : new VaultSettings(id);
|
||||||
settings.setMountName(mountName);
|
settings.mountName().set(mountName);
|
||||||
settings.setPath(Paths.get(path));
|
settings.path().set(Paths.get(path));
|
||||||
settings.setWinDriveLetter(winDriveLetter);
|
settings.winDriveLetter().set(winDriveLetter);
|
||||||
return settings;
|
return settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,8 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2017 Skymatic UG (haftungsbeschränkt).
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the accompanying LICENSE file.
|
||||||
|
*******************************************************************************/
|
||||||
package org.cryptomator.ui.util;
|
package org.cryptomator.ui.util;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|||||||
@@ -1,3 +1,8 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2017 Skymatic UG (haftungsbeschränkt).
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the accompanying LICENSE file.
|
||||||
|
*******************************************************************************/
|
||||||
package org.cryptomator.ui.util;
|
package org.cryptomator.ui.util;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|||||||
@@ -16,6 +16,8 @@
|
|||||||
<?import javafx.scene.control.TextField?>
|
<?import javafx.scene.control.TextField?>
|
||||||
<?import javafx.scene.layout.VBox?>
|
<?import javafx.scene.layout.VBox?>
|
||||||
<?import javafx.scene.control.ChoiceBox?>
|
<?import javafx.scene.control.ChoiceBox?>
|
||||||
|
<?import javafx.scene.layout.HBox?>
|
||||||
|
<?import javafx.scene.control.Button?>
|
||||||
|
|
||||||
<VBox prefWidth="400.0" alignment="TOP_CENTER" spacing="12.0" xmlns:fx="http://javafx.com/fxml" cacheShape="true" cache="true">
|
<VBox prefWidth="400.0" alignment="TOP_CENTER" spacing="12.0" xmlns:fx="http://javafx.com/fxml" cacheShape="true" cache="true">
|
||||||
<Label VBox.vgrow="NEVER" fx:id="versionLabel" alignment="CENTER" cacheShape="true" cache="true" />
|
<Label VBox.vgrow="NEVER" fx:id="versionLabel" alignment="CENTER" cacheShape="true" cache="true" />
|
||||||
@@ -36,7 +38,11 @@
|
|||||||
|
|
||||||
<!-- Row 1 -->
|
<!-- Row 1 -->
|
||||||
<Label GridPane.rowIndex="1" GridPane.columnIndex="0" text="%settings.port.label" cacheShape="true" cache="true" />
|
<Label GridPane.rowIndex="1" GridPane.columnIndex="0" text="%settings.port.label" cacheShape="true" cache="true" />
|
||||||
<TextField GridPane.rowIndex="1" GridPane.columnIndex="1" fx:id="portField" cacheShape="true" cache="true" promptText="%settings.port.prompt" />
|
<HBox GridPane.rowIndex="1" GridPane.columnIndex="1" spacing="6.0">
|
||||||
|
<TextField fx:id="portField" cacheShape="true" cache="true" promptText="%settings.port.prompt" />
|
||||||
|
<Button text="%settings.port.apply" fx:id="changePortButton" onAction="#changePort"/>
|
||||||
|
</HBox>
|
||||||
|
|
||||||
|
|
||||||
<!-- Row 2 -->
|
<!-- Row 2 -->
|
||||||
<Label GridPane.rowIndex="2" GridPane.columnIndex="0" fx:id="useIpv6Label" text="%settings.useipv6.label" cacheShape="true" cache="true" />
|
<Label GridPane.rowIndex="2" GridPane.columnIndex="0" fx:id="useIpv6Label" text="%settings.useipv6.label" cacheShape="true" cache="true" />
|
||||||
|
|||||||
@@ -98,8 +98,9 @@ unlocked.ioGraph.yAxis.label=Throughput (MiB/s)
|
|||||||
# settings.fxml
|
# settings.fxml
|
||||||
settings.version.label=Version %s
|
settings.version.label=Version %s
|
||||||
settings.checkForUpdates.label=Check for Updates
|
settings.checkForUpdates.label=Check for Updates
|
||||||
settings.port.label=WebDAV Port *
|
settings.port.label=WebDAV Port
|
||||||
settings.port.prompt=0 = Choose automatically
|
settings.port.prompt=0 = Choose automatically
|
||||||
|
settings.port.apply=Apply
|
||||||
settings.useipv6.label=Use IPv6 Literal
|
settings.useipv6.label=Use IPv6 Literal
|
||||||
settings.prefGvfsScheme.label=WebDAV Scheme
|
settings.prefGvfsScheme.label=WebDAV Scheme
|
||||||
settings.debugMode.label=Debug Mode *
|
settings.debugMode.label=Debug Mode *
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2017 Skymatic UG (haftungsbeschränkt).
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the accompanying LICENSE file.
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.cryptomator.ui.settings;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class SettingsJsonAdapterTest {
|
||||||
|
|
||||||
|
private final SettingsJsonAdapter adapter = new SettingsJsonAdapter(this::noop);
|
||||||
|
|
||||||
|
private void noop(Settings settings) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDeserialize() throws IOException {
|
||||||
|
String vault1Json = "{\"id\": \"1\", \"path\": \"/vault1\", \"mountName\": \"vault1\", \"winDriveLetter\": \"X\"}";
|
||||||
|
String vault2Json = "{\"id\": \"2\", \"path\": \"/vault2\", \"mountName\": \"vault2\", \"winDriveLetter\": \"Y\"}";
|
||||||
|
String json = "{\"directories\": [" + vault1Json + "," + vault2Json + "]," //
|
||||||
|
+ "\"checkForUpdatesEnabled\": true,"//
|
||||||
|
+ "\"port\": 8080,"//
|
||||||
|
+ "\"useIpv6\": true,"//
|
||||||
|
+ "\"numTrayNotifications\": 42}";
|
||||||
|
|
||||||
|
Settings settings = adapter.fromJson(json);
|
||||||
|
|
||||||
|
Assert.assertTrue(settings.checkForUpdates().get());
|
||||||
|
Assert.assertEquals(2, settings.getDirectories().size());
|
||||||
|
Assert.assertEquals(8080, settings.port().get());
|
||||||
|
Assert.assertTrue(settings.useIpv6().get());
|
||||||
|
Assert.assertEquals(42, settings.numTrayNotifications().get());
|
||||||
|
Assert.assertEquals("dav", settings.preferredGvfsScheme().get());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2017 Skymatic UG (haftungsbeschränkt).
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the accompanying LICENSE file.
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.cryptomator.ui.settings;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class VaultSettingsJsonAdapterTest {
|
||||||
|
|
||||||
|
private final VaultSettingsJsonAdapter adapter = new VaultSettingsJsonAdapter();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDeserialize() throws IOException {
|
||||||
|
VaultSettings settings = adapter.fromJson("{\"id\": \"foo\", \"path\": \"/foo/bar\", \"mountName\": \"test\", \"winDriveLetter\": \"X\", \"shouldBeIgnored\": true}");
|
||||||
|
Assert.assertEquals("foo", settings.getId());
|
||||||
|
Assert.assertEquals(Paths.get("/foo/bar"), settings.path().get());
|
||||||
|
Assert.assertEquals("test", settings.mountName().get());
|
||||||
|
Assert.assertEquals("X", settings.winDriveLetter().get());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user