mirror of
https://github.com/cryptomator/cryptomator.git
synced 2026-09-20 06:54:16 +00:00
Merge branch 'develop' into feature/fuse-integration
# Conflicts: # main/commons/pom.xml # main/pom.xml
This commit is contained in:
@@ -66,20 +66,12 @@
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- DI -->
|
||||
<dependency>
|
||||
<groupId>com.google.dagger</groupId>
|
||||
<artifactId>dagger</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.dagger</groupId>
|
||||
<artifactId>dagger-compiler</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Zxcvbn -->
|
||||
<dependency>
|
||||
|
||||
@@ -16,22 +16,20 @@ import java.util.function.Consumer;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import javafx.beans.binding.Binding;
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
import org.cryptomator.common.CommonsModule;
|
||||
import org.cryptomator.common.settings.Settings;
|
||||
import org.cryptomator.common.settings.SettingsProvider;
|
||||
import org.cryptomator.frontend.webdav.WebDavServer;
|
||||
import org.cryptomator.jni.JniModule;
|
||||
import org.cryptomator.keychain.KeychainModule;
|
||||
import org.cryptomator.ui.controllers.ViewControllerModule;
|
||||
import org.cryptomator.ui.model.VaultComponent;
|
||||
import org.fxmisc.easybind.EasyBind;
|
||||
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import javafx.beans.binding.Binding;
|
||||
|
||||
@Module(includes = {ViewControllerModule.class, CommonsModule.class, KeychainModule.class, JniModule.class}, subcomponents = {VaultComponent.class})
|
||||
@Module(includes = {ViewControllerModule.class, CommonsModule.class, KeychainModule.class}, subcomponents = {VaultComponent.class})
|
||||
public class UiModule {
|
||||
|
||||
@Provides
|
||||
|
||||
@@ -9,8 +9,7 @@
|
||||
******************************************************************************/
|
||||
package org.cryptomator.ui.controllers;
|
||||
|
||||
import static org.cryptomator.ui.util.DialogBuilderUtil.buildErrorDialog;
|
||||
|
||||
import java.awt.Desktop;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@@ -28,25 +27,6 @@ import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
import org.cryptomator.common.settings.VaultSettings;
|
||||
import org.cryptomator.ui.ExitUtil;
|
||||
import org.cryptomator.ui.controls.DirectoryListCell;
|
||||
import org.cryptomator.ui.l10n.Localization;
|
||||
import org.cryptomator.ui.model.AutoUnlocker;
|
||||
import org.cryptomator.ui.model.UpgradeStrategies;
|
||||
import org.cryptomator.ui.model.UpgradeStrategy;
|
||||
import org.cryptomator.ui.model.Vault;
|
||||
import org.cryptomator.ui.model.VaultFactory;
|
||||
import org.cryptomator.ui.model.VaultList;
|
||||
import org.cryptomator.ui.util.DialogBuilderUtil;
|
||||
import org.cryptomator.ui.util.EawtApplicationWrapper;
|
||||
import org.fxmisc.easybind.EasyBind;
|
||||
import org.fxmisc.easybind.Subscription;
|
||||
import org.fxmisc.easybind.monadic.MonadicBinding;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javafx.application.Application;
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.binding.Binding;
|
||||
@@ -81,6 +61,25 @@ import javafx.scene.layout.Pane;
|
||||
import javafx.scene.text.Font;
|
||||
import javafx.stage.FileChooser;
|
||||
import javafx.stage.Stage;
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
import org.cryptomator.common.settings.VaultSettings;
|
||||
import org.cryptomator.ui.ExitUtil;
|
||||
import org.cryptomator.ui.controls.DirectoryListCell;
|
||||
import org.cryptomator.ui.l10n.Localization;
|
||||
import org.cryptomator.ui.model.AutoUnlocker;
|
||||
import org.cryptomator.ui.model.UpgradeStrategies;
|
||||
import org.cryptomator.ui.model.UpgradeStrategy;
|
||||
import org.cryptomator.ui.model.Vault;
|
||||
import org.cryptomator.ui.model.VaultFactory;
|
||||
import org.cryptomator.ui.model.VaultList;
|
||||
import org.cryptomator.ui.util.DialogBuilderUtil;
|
||||
import org.fxmisc.easybind.EasyBind;
|
||||
import org.fxmisc.easybind.Subscription;
|
||||
import org.fxmisc.easybind.monadic.MonadicBinding;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static org.cryptomator.ui.util.DialogBuilderUtil.buildErrorDialog;
|
||||
|
||||
@Singleton
|
||||
public class MainController implements ViewController {
|
||||
@@ -129,11 +128,13 @@ public class MainController implements ViewController {
|
||||
EasyBind.subscribe(areAllVaultsLocked, Platform::setImplicitExit);
|
||||
autoUnlocker.unlockAllSilently();
|
||||
|
||||
EawtApplicationWrapper.getApplication().ifPresent(app -> {
|
||||
app.setPreferencesHandler(() -> {
|
||||
try {
|
||||
Desktop.getDesktop().setPreferencesHandler(e -> {
|
||||
Platform.runLater(this::toggleShowSettings);
|
||||
});
|
||||
});
|
||||
} catch (UnsupportedOperationException e) {
|
||||
LOG.info("Unable to setPreferencesHandler, probably not supported on this OS.");
|
||||
}
|
||||
}
|
||||
|
||||
@FXML
|
||||
|
||||
@@ -8,11 +8,10 @@
|
||||
******************************************************************************/
|
||||
package org.cryptomator.ui.controllers;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.Duration;
|
||||
import java.util.Comparator;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
@@ -22,23 +21,9 @@ import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
import org.apache.http.client.config.RequestConfig;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.cryptomator.common.settings.Settings;
|
||||
import org.cryptomator.ui.l10n.Localization;
|
||||
import org.cryptomator.ui.util.AsyncTaskService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
|
||||
import javafx.application.Application;
|
||||
import javafx.application.Platform;
|
||||
import javafx.event.ActionEvent;
|
||||
@@ -49,6 +34,15 @@ import javafx.scene.control.Hyperlink;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.ProgressIndicator;
|
||||
import javafx.scene.layout.VBox;
|
||||
import jdk.incubator.http.HttpClient;
|
||||
import jdk.incubator.http.HttpRequest;
|
||||
import jdk.incubator.http.HttpResponse;
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
import org.cryptomator.common.settings.Settings;
|
||||
import org.cryptomator.ui.l10n.Localization;
|
||||
import org.cryptomator.ui.util.AsyncTaskService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@Singleton
|
||||
public class WelcomeController implements ViewController {
|
||||
@@ -114,31 +108,21 @@ public class WelcomeController implements ViewController {
|
||||
checkForUpdatesStatus.setText(localization.getString("welcome.checkForUpdates.label.currentlyChecking"));
|
||||
checkForUpdatesIndicator.setVisible(true);
|
||||
asyncTaskService.asyncTaskOf(() -> {
|
||||
RequestConfig requestConfig = RequestConfig.custom() //
|
||||
.setConnectTimeout(5000) //
|
||||
.setConnectionRequestTimeout(5000) //
|
||||
.setSocketTimeout(5000) //
|
||||
.build();
|
||||
String userAgent = String.format("Cryptomator VersionChecker/%s %s %s (%s)", applicationVersion.orElse("SNAPSHOT"), SystemUtils.OS_NAME, SystemUtils.OS_VERSION, SystemUtils.OS_ARCH);
|
||||
HttpClientBuilder httpClientBuilder = HttpClients.custom() //
|
||||
.disableCookieManagement() //
|
||||
.setDefaultRequestConfig(requestConfig) //
|
||||
.setUserAgent(userAgent);
|
||||
LOG.debug("Checking for updates...");
|
||||
try (CloseableHttpClient client = httpClientBuilder.build()) {
|
||||
HttpGet request = new HttpGet("https://api.cryptomator.org/updates/latestVersion.json");
|
||||
try (CloseableHttpResponse response = client.execute(request)) {
|
||||
if (response.getStatusLine().getStatusCode() == 200 && response.getEntity() != null) {
|
||||
try (InputStream in = response.getEntity().getContent()) {
|
||||
Gson gson = new GsonBuilder().setLenient().create();
|
||||
Reader utf8Reader = new InputStreamReader(in, StandardCharsets.UTF_8);
|
||||
Map<String, String> map = gson.fromJson(utf8Reader, new TypeToken<Map<String, String>>() {
|
||||
}.getType());
|
||||
if (map != null) {
|
||||
this.compareVersions(map);
|
||||
}
|
||||
}
|
||||
}
|
||||
HttpClient client = HttpClient.newHttpClient();
|
||||
HttpRequest request = HttpRequest.newBuilder()
|
||||
.GET()
|
||||
.uri(new URI("https://api.cryptomator.org/updates/latestVersion.json"))
|
||||
.header("User-Agent", userAgent)
|
||||
.timeout(Duration.ofSeconds(5))
|
||||
.build();
|
||||
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandler.asString(StandardCharsets.UTF_8));
|
||||
if (response.statusCode() == 200) {
|
||||
Gson gson = new GsonBuilder().setLenient().create();
|
||||
Map<String, String> map = gson.fromJson(response.body(), new TypeToken<Map<String, String>>() {
|
||||
}.getType());
|
||||
if (map != null) {
|
||||
this.compareVersions(map);
|
||||
}
|
||||
}
|
||||
}).andFinally(() -> {
|
||||
|
||||
@@ -38,6 +38,11 @@ public class VaultList extends TransformationList<Vault, VaultSettings> {
|
||||
return index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getViewIndex(int index) {
|
||||
return index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vault get(int index) {
|
||||
VaultSettings s = source.get(index);
|
||||
|
||||
@@ -1,127 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* 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;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
import org.cryptomator.common.SupplierThrowingException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Reflection-based wrapper for com.apple.eawt.Application.
|
||||
*/
|
||||
public class EawtApplicationWrapper {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(EawtApplicationWrapper.class);
|
||||
|
||||
private final Class<?> applicationClass;
|
||||
private final Object application;
|
||||
|
||||
private EawtApplicationWrapper() throws ReflectiveOperationException {
|
||||
this.applicationClass = Class.forName("com.apple.eawt.Application");
|
||||
this.application = applicationClass.getMethod("getApplication").invoke(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A wrapper for com.apple.ewat.Application if the current OS is macOS and the class is available in this JVM.
|
||||
*/
|
||||
public static Optional<EawtApplicationWrapper> getApplication() {
|
||||
if (!SystemUtils.IS_OS_MAC_OSX) {
|
||||
return Optional.empty();
|
||||
}
|
||||
try {
|
||||
return Optional.of(new EawtApplicationWrapper());
|
||||
} catch (ReflectiveOperationException e) {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
private void setOpenFileHandler(InvocationHandler handler) throws ReflectiveOperationException {
|
||||
Class<?> handlerClass = Class.forName("com.apple.eawt.OpenFilesHandler");
|
||||
Method setter = applicationClass.getMethod("setOpenFileHandler", handlerClass);
|
||||
Object proxy = Proxy.newProxyInstance(applicationClass.getClassLoader(), new Class<?>[] {handlerClass}, handler);
|
||||
setter.invoke(application, proxy);
|
||||
}
|
||||
|
||||
public void setOpenFileHandler(Consumer<List<File>> handler) {
|
||||
try {
|
||||
Class<?> openFilesEventClass = Class.forName("com.apple.eawt.AppEvent$OpenFilesEvent");
|
||||
Method getFiles = openFilesEventClass.getMethod("getFiles");
|
||||
setOpenFileHandler(methodSpecificInvocationHandler("openFiles", args -> {
|
||||
Object openFilesEvent = args[0];
|
||||
assert openFilesEventClass.isInstance(openFilesEvent);
|
||||
@SuppressWarnings("unchecked")
|
||||
List<File> files = (List<File>) uncheckedReflectiveOperation(() -> getFiles.invoke(openFilesEvent));
|
||||
handler.accept(files);
|
||||
return null;
|
||||
}));
|
||||
} catch (ReflectiveOperationException e) {
|
||||
LOG.error("Exception setting openFileHandler.", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void setPreferencesHandler(InvocationHandler handler) throws ReflectiveOperationException {
|
||||
Class<?> handlerClass = Class.forName("com.apple.eawt.PreferencesHandler");
|
||||
Method setter = applicationClass.getMethod("setPreferencesHandler", handlerClass);
|
||||
Object proxy = Proxy.newProxyInstance(applicationClass.getClassLoader(), new Class<?>[] {handlerClass}, handler);
|
||||
setter.invoke(application, proxy);
|
||||
}
|
||||
|
||||
public void setPreferencesHandler(Runnable handler) {
|
||||
try {
|
||||
setPreferencesHandler(methodSpecificInvocationHandler("handlePreferences", args -> {
|
||||
handler.run();
|
||||
return null;
|
||||
}));
|
||||
} catch (ReflectiveOperationException e) {
|
||||
LOG.error("Exception setting preferencesHandler.", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static InvocationHandler methodSpecificInvocationHandler(String methodName, Function<Object[], Object> handler) {
|
||||
return new InvocationHandler() {
|
||||
@Override
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
if (method.getName().equals(methodName)) {
|
||||
return handler.apply(args);
|
||||
} else {
|
||||
throw new UnsupportedOperationException("Unexpected invocation " + method.getName() + ", expected " + methodName);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps {@link ReflectiveOperationException}s as {@link UncheckedReflectiveOperationException}.
|
||||
*
|
||||
* @param operation Invokation throwing an ReflectiveOperationException
|
||||
* @return Result returned by <code>operation</code>
|
||||
* @throws UncheckedReflectiveOperationException in case <code>operation</code> throws an ReflectiveOperationException.
|
||||
*/
|
||||
private static <T> T uncheckedReflectiveOperation(SupplierThrowingException<T, ReflectiveOperationException> operation) throws UncheckedReflectiveOperationException {
|
||||
try {
|
||||
return operation.get();
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new UncheckedReflectiveOperationException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static class UncheckedReflectiveOperationException extends RuntimeException {
|
||||
public UncheckedReflectiveOperationException(ReflectiveOperationException cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user