From f880db490212dc1dec3f7ca23803387da5c13501 Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Wed, 10 Jul 2019 15:14:23 +0200 Subject: [PATCH 001/264] fixes #842 --- .../launcher/CleanShutdownPerformer.java | 24 +++++--- .../org/cryptomator/launcher/Cryptomator.java | 56 +++++++------------ .../launcher/CryptomatorComponent.java | 3 +- .../launcher/CryptomatorModule.java | 16 ++++++ .../launcher/FxApplicationComponent.java | 36 ------------ .../java/org/cryptomator/ui/ExitUtil.java | 1 - .../org/cryptomator/ui/FxApplication.java | 39 +++++++++++++ .../ui/FxApplicationComponent.java | 16 ++++++ .../cryptomator/ui}/FxApplicationModule.java | 23 +++++--- .../cryptomator/ui}/FxApplicationScoped.java | 2 +- .../java/org/cryptomator/ui/UiModule.java | 1 - .../ui/controllers/MainController.java | 2 +- .../ui/controllers/NotFoundController.java | 2 +- .../ui/controllers/SettingsController.java | 3 +- .../ui/controllers/ViewControllerLoader.java | 2 +- .../ui/controllers/WelcomeController.java | 2 +- .../org/cryptomator/ui/l10n/Localization.java | 2 +- .../cryptomator/ui/model/AutoUnlocker.java | 2 +- .../cryptomator/ui/model/VaultFactory.java | 2 +- .../org/cryptomator/ui/model/VaultList.java | 2 +- .../ui/model/WindowsDriveLetters.java | 2 +- .../ui/model/upgrade/UpgradeStrategies.java | 2 +- .../UpgradeVersion3DropBundleExtension.java | 2 +- .../ui/model/upgrade/UpgradeVersion3to4.java | 2 +- .../ui/model/upgrade/UpgradeVersion4to5.java | 2 +- .../ui/model/upgrade/UpgradeVersion5toX.java | 2 +- .../ui/util/PasswordStrengthUtil.java | 2 +- 27 files changed, 142 insertions(+), 108 deletions(-) delete mode 100644 main/launcher/src/main/java/org/cryptomator/launcher/FxApplicationComponent.java create mode 100644 main/ui/src/main/java/org/cryptomator/ui/FxApplication.java create mode 100644 main/ui/src/main/java/org/cryptomator/ui/FxApplicationComponent.java rename main/{launcher/src/main/java/org/cryptomator/launcher => ui/src/main/java/org/cryptomator/ui}/FxApplicationModule.java (55%) rename main/{commons/src/main/java/org/cryptomator/common => ui/src/main/java/org/cryptomator/ui}/FxApplicationScoped.java (88%) diff --git a/main/launcher/src/main/java/org/cryptomator/launcher/CleanShutdownPerformer.java b/main/launcher/src/main/java/org/cryptomator/launcher/CleanShutdownPerformer.java index 8a2c23dcc..717fb86a8 100644 --- a/main/launcher/src/main/java/org/cryptomator/launcher/CleanShutdownPerformer.java +++ b/main/launcher/src/main/java/org/cryptomator/launcher/CleanShutdownPerformer.java @@ -11,30 +11,38 @@ import java.util.concurrent.ConcurrentMap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.inject.Inject; +import javax.inject.Singleton; + +@Singleton class CleanShutdownPerformer extends Thread { private static final Logger LOG = LoggerFactory.getLogger(CleanShutdownPerformer.class); - static final ConcurrentMap SHUTDOWN_TASKS = new ConcurrentHashMap<>(); + private final ConcurrentMap tasks = new ConcurrentHashMap<>(); + + @Inject + CleanShutdownPerformer() { + super(null, null, "ShutdownTasks", 0); + } @Override public void run() { LOG.debug("Running graceful shutdown tasks..."); - SHUTDOWN_TASKS.keySet().forEach(r -> { + tasks.keySet().forEach(r -> { try { r.run(); } catch (RuntimeException e) { LOG.error("Exception while shutting down.", e); } }); - SHUTDOWN_TASKS.clear(); - LOG.info("Goodbye."); + tasks.clear(); } - static void scheduleShutdownTask(Runnable task) { - SHUTDOWN_TASKS.put(task, Boolean.TRUE); + void scheduleShutdownTask(Runnable task) { + tasks.put(task, Boolean.TRUE); } - static void registerShutdownHook() { - Runtime.getRuntime().addShutdownHook(new CleanShutdownPerformer()); + void registerShutdownHook() { + Runtime.getRuntime().addShutdownHook(this); } } \ No newline at end of file diff --git a/main/launcher/src/main/java/org/cryptomator/launcher/Cryptomator.java b/main/launcher/src/main/java/org/cryptomator/launcher/Cryptomator.java index 8651553e3..71f43a100 100644 --- a/main/launcher/src/main/java/org/cryptomator/launcher/Cryptomator.java +++ b/main/launcher/src/main/java/org/cryptomator/launcher/Cryptomator.java @@ -5,12 +5,11 @@ *******************************************************************************/ package org.cryptomator.launcher; -import javafx.application.Application; -import javafx.stage.Stage; +import javafx.application.Platform; import org.apache.commons.lang3.SystemUtils; import org.cryptomator.logging.DebugMode; import org.cryptomator.logging.LoggerConfiguration; -import org.cryptomator.ui.controllers.MainController; +import org.cryptomator.ui.FxApplication; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -19,6 +18,7 @@ import javax.inject.Named; import javax.inject.Singleton; import java.io.IOException; import java.util.Optional; +import java.util.concurrent.CountDownLatch; @Singleton public class Cryptomator { @@ -32,13 +32,17 @@ public class Cryptomator { private final DebugMode debugMode; private final IpcFactory ipcFactory; private final Optional applicationVersion; + private final CountDownLatch shutdownLatch; + private final CleanShutdownPerformer shutdownPerformer; @Inject - Cryptomator(LoggerConfiguration logConfig, DebugMode debugMode, IpcFactory ipcFactory, @Named("applicationVersion") Optional applicationVersion) { + Cryptomator(LoggerConfiguration logConfig, DebugMode debugMode, IpcFactory ipcFactory, @Named("applicationVersion") Optional applicationVersion, @Named("shutdownLatch") CountDownLatch shutdownLatch, CleanShutdownPerformer shutdownPerformer) { this.logConfig = logConfig; this.debugMode = debugMode; this.ipcFactory = ipcFactory; this.applicationVersion = applicationVersion; + this.shutdownLatch = shutdownLatch; + this.shutdownPerformer = shutdownPerformer; } public static void main(String[] args) { @@ -48,6 +52,7 @@ public class Cryptomator { /** * Main entry point of the application launcher. + * * @param args The arguments passed to this program via {@link #main(String[])}. * @return Nonzero exit code in case of an error. */ @@ -77,45 +82,26 @@ public class Cryptomator { /** * Launches the JavaFX application and waits until shutdown is requested. + * * @return Nonzero exit code in case of an error. + * @implNote This method blocks until {@link #shutdownLatch} reached zero. */ private int runGuiApplication() { try { - CleanShutdownPerformer.registerShutdownHook(); - Application.launch(MainApp.class); - LOG.info("Shutting down..."); + shutdownPerformer.registerShutdownHook(); + Platform.startup(() -> { + assert Platform.isFxApplicationThread(); + FxApplication app = CRYPTOMATOR_COMPONENT.fxApplicationComponent().application(); + app.start(); + }); + shutdownLatch.await(); + LOG.info("UI shut down"); return 0; - } catch (Throwable e) { - LOG.error("Terminating due to error", e); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); return 1; } } - // We need a separate FX Application class, until we can use the module system. See https://stackoverflow.com/q/54756176/4014509 - public static class MainApp extends Application { - - @Override - public void start(Stage primaryStage) { - LOG.info("JavaFX application started."); - primaryStage.setMinWidth(652.0); - primaryStage.setMinHeight(440.0); - - FxApplicationComponent fxApplicationComponent = CRYPTOMATOR_COMPONENT.fxApplicationComponent() // - .fxApplication(this) // - .mainWindow(primaryStage) // - .build(); - - MainController mainCtrl = fxApplicationComponent.fxmlLoader().load("/fxml/main.fxml"); - mainCtrl.initStage(primaryStage); - primaryStage.show(); - } - - @Override - public void stop() { - LOG.info("JavaFX application stopped."); - } - - } - } diff --git a/main/launcher/src/main/java/org/cryptomator/launcher/CryptomatorComponent.java b/main/launcher/src/main/java/org/cryptomator/launcher/CryptomatorComponent.java index 6d5c47b05..251e0ce48 100644 --- a/main/launcher/src/main/java/org/cryptomator/launcher/CryptomatorComponent.java +++ b/main/launcher/src/main/java/org/cryptomator/launcher/CryptomatorComponent.java @@ -3,6 +3,7 @@ package org.cryptomator.launcher; import dagger.Component; import org.cryptomator.common.CommonsModule; import org.cryptomator.logging.LoggerModule; +import org.cryptomator.ui.FxApplicationComponent; import javax.inject.Singleton; @@ -12,6 +13,6 @@ public interface CryptomatorComponent { Cryptomator application(); - FxApplicationComponent.Builder fxApplicationComponent(); + FxApplicationComponent fxApplicationComponent(); } diff --git a/main/launcher/src/main/java/org/cryptomator/launcher/CryptomatorModule.java b/main/launcher/src/main/java/org/cryptomator/launcher/CryptomatorModule.java index 2fe1f393a..37c8b2216 100644 --- a/main/launcher/src/main/java/org/cryptomator/launcher/CryptomatorModule.java +++ b/main/launcher/src/main/java/org/cryptomator/launcher/CryptomatorModule.java @@ -4,6 +4,7 @@ import dagger.Module; import dagger.Provides; import org.cryptomator.common.settings.Settings; import org.cryptomator.common.settings.SettingsProvider; +import org.cryptomator.ui.FxApplicationScoped; import org.cryptomator.ui.model.AppLaunchEvent; import javax.inject.Named; @@ -12,10 +13,25 @@ import java.util.Optional; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.CountDownLatch; +import java.util.function.Consumer; @Module class CryptomatorModule { + @Provides + @Singleton + @Named("shutdownTaskScheduler") + Consumer provideShutdownTaskScheduler(CleanShutdownPerformer shutdownPerformer) { + return shutdownPerformer::scheduleShutdownTask; + } + + @Provides + @Singleton + @Named("shutdownLatch") + static CountDownLatch provideShutdownLatch() { + return new CountDownLatch(1); + } + @Provides @Singleton static Settings provideSettings(SettingsProvider settingsProvider) { diff --git a/main/launcher/src/main/java/org/cryptomator/launcher/FxApplicationComponent.java b/main/launcher/src/main/java/org/cryptomator/launcher/FxApplicationComponent.java deleted file mode 100644 index 562151f43..000000000 --- a/main/launcher/src/main/java/org/cryptomator/launcher/FxApplicationComponent.java +++ /dev/null @@ -1,36 +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.launcher; - -import dagger.BindsInstance; -import dagger.Subcomponent; -import javafx.application.Application; -import javafx.stage.Stage; -import org.cryptomator.common.FxApplicationScoped; -import org.cryptomator.ui.controllers.ViewControllerLoader; - -import javax.inject.Named; - -@FxApplicationScoped -@Subcomponent(modules = FxApplicationModule.class) -interface FxApplicationComponent { - - ViewControllerLoader fxmlLoader(); - - @Subcomponent.Builder - interface Builder { - - @BindsInstance - Builder fxApplication(Application application); - - @BindsInstance - Builder mainWindow(@Named("mainWindow") Stage mainWindow); - - FxApplicationComponent build(); - - } - -} diff --git a/main/ui/src/main/java/org/cryptomator/ui/ExitUtil.java b/main/ui/src/main/java/org/cryptomator/ui/ExitUtil.java index ba51b6622..335f1d1ca 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/ExitUtil.java +++ b/main/ui/src/main/java/org/cryptomator/ui/ExitUtil.java @@ -12,7 +12,6 @@ package org.cryptomator.ui; import javafx.application.Platform; import javafx.stage.Stage; import org.apache.commons.lang3.SystemUtils; -import org.cryptomator.common.FxApplicationScoped; import org.cryptomator.common.settings.Settings; import org.cryptomator.jni.JniException; import org.cryptomator.jni.MacApplicationUiState; diff --git a/main/ui/src/main/java/org/cryptomator/ui/FxApplication.java b/main/ui/src/main/java/org/cryptomator/ui/FxApplication.java new file mode 100644 index 000000000..f8136479f --- /dev/null +++ b/main/ui/src/main/java/org/cryptomator/ui/FxApplication.java @@ -0,0 +1,39 @@ +package org.cryptomator.ui; + +import javafx.application.Application; +import javafx.stage.Stage; +import org.cryptomator.ui.controllers.MainController; +import org.cryptomator.ui.controllers.ViewControllerLoader; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.inject.Inject; +import javax.inject.Named; + +@FxApplicationScoped +public class FxApplication extends Application { + + private static final Logger LOG = LoggerFactory.getLogger(FxApplication.class); + + private final Stage primaryStage; + private final ViewControllerLoader fxmlLoader; + + @Inject + FxApplication(@Named("mainWindow") Stage primaryStage, ViewControllerLoader fxmlLoader) { + this.primaryStage = primaryStage; + this.fxmlLoader = fxmlLoader; + } + + public void start() { + LOG.info("Starting GUI..."); + start(primaryStage); + } + + @Override + public void start(Stage primaryStage) { + MainController mainCtrl = fxmlLoader.load("/fxml/main.fxml"); + mainCtrl.initStage(primaryStage); + primaryStage.show(); + } + +} diff --git a/main/ui/src/main/java/org/cryptomator/ui/FxApplicationComponent.java b/main/ui/src/main/java/org/cryptomator/ui/FxApplicationComponent.java new file mode 100644 index 000000000..5b029a50c --- /dev/null +++ b/main/ui/src/main/java/org/cryptomator/ui/FxApplicationComponent.java @@ -0,0 +1,16 @@ +/******************************************************************************* + * 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; + +import dagger.Subcomponent; + +@FxApplicationScoped +@Subcomponent(modules = FxApplicationModule.class) +public interface FxApplicationComponent { + + FxApplication application(); + +} diff --git a/main/launcher/src/main/java/org/cryptomator/launcher/FxApplicationModule.java b/main/ui/src/main/java/org/cryptomator/ui/FxApplicationModule.java similarity index 55% rename from main/launcher/src/main/java/org/cryptomator/launcher/FxApplicationModule.java rename to main/ui/src/main/java/org/cryptomator/ui/FxApplicationModule.java index 1d9988d06..5482dd189 100644 --- a/main/launcher/src/main/java/org/cryptomator/launcher/FxApplicationModule.java +++ b/main/ui/src/main/java/org/cryptomator/ui/FxApplicationModule.java @@ -3,24 +3,31 @@ * All rights reserved. This program and the accompanying materials * are made available under the terms of the accompanying LICENSE file. *******************************************************************************/ -package org.cryptomator.launcher; +package org.cryptomator.ui; +import dagger.Binds; import dagger.Module; import dagger.Provides; -import org.cryptomator.common.FxApplicationScoped; -import org.cryptomator.ui.UiModule; +import javafx.application.Application; +import javafx.stage.Stage; import javax.inject.Named; -import java.util.function.Consumer; @Module(includes = {UiModule.class}) -class FxApplicationModule { +abstract class FxApplicationModule { @Provides @FxApplicationScoped - @Named("shutdownTaskScheduler") - Consumer provideShutdownTaskScheduler() { - return CleanShutdownPerformer::scheduleShutdownTask; + @Named("mainWindow") + static Stage providePrimaryStage() { + Stage stage = new Stage(); + stage.setMinWidth(652.0); + stage.setMinHeight(440.0); + return stage; } + @Binds + @FxApplicationScoped + abstract Application provideApplication(FxApplication application); + } diff --git a/main/commons/src/main/java/org/cryptomator/common/FxApplicationScoped.java b/main/ui/src/main/java/org/cryptomator/ui/FxApplicationScoped.java similarity index 88% rename from main/commons/src/main/java/org/cryptomator/common/FxApplicationScoped.java rename to main/ui/src/main/java/org/cryptomator/ui/FxApplicationScoped.java index dd90f4a38..e60c167df 100644 --- a/main/commons/src/main/java/org/cryptomator/common/FxApplicationScoped.java +++ b/main/ui/src/main/java/org/cryptomator/ui/FxApplicationScoped.java @@ -1,4 +1,4 @@ -package org.cryptomator.common; +package org.cryptomator.ui; import javax.inject.Scope; import java.lang.annotation.Documented; diff --git a/main/ui/src/main/java/org/cryptomator/ui/UiModule.java b/main/ui/src/main/java/org/cryptomator/ui/UiModule.java index b93c5ddae..6c09147e1 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/UiModule.java +++ b/main/ui/src/main/java/org/cryptomator/ui/UiModule.java @@ -12,7 +12,6 @@ import dagger.Module; import dagger.Provides; import javafx.beans.binding.Binding; import org.apache.commons.lang3.SystemUtils; -import org.cryptomator.common.FxApplicationScoped; import org.cryptomator.common.settings.Settings; import org.cryptomator.frontend.webdav.WebDavServer; import org.cryptomator.keychain.KeychainModule; diff --git a/main/ui/src/main/java/org/cryptomator/ui/controllers/MainController.java b/main/ui/src/main/java/org/cryptomator/ui/controllers/MainController.java index 9e435e389..59667a2fc 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/controllers/MainController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/controllers/MainController.java @@ -44,7 +44,7 @@ import javafx.stage.FileChooser; import javafx.stage.Stage; import javafx.util.Duration; import org.apache.commons.lang3.SystemUtils; -import org.cryptomator.common.FxApplicationScoped; +import org.cryptomator.ui.FxApplicationScoped; import org.cryptomator.common.settings.VaultSettings; import org.cryptomator.ui.ExitUtil; import org.cryptomator.ui.controls.DirectoryListCell; diff --git a/main/ui/src/main/java/org/cryptomator/ui/controllers/NotFoundController.java b/main/ui/src/main/java/org/cryptomator/ui/controllers/NotFoundController.java index 8d4408111..f579d51d0 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/controllers/NotFoundController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/controllers/NotFoundController.java @@ -8,7 +8,7 @@ package org.cryptomator.ui.controllers; import javafx.fxml.FXML; import javafx.scene.Parent; import javafx.scene.layout.VBox; -import org.cryptomator.common.FxApplicationScoped; +import org.cryptomator.ui.FxApplicationScoped; import javax.inject.Inject; diff --git a/main/ui/src/main/java/org/cryptomator/ui/controllers/SettingsController.java b/main/ui/src/main/java/org/cryptomator/ui/controllers/SettingsController.java index f055573c5..b2af10cbe 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/controllers/SettingsController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/controllers/SettingsController.java @@ -12,7 +12,6 @@ import com.google.common.base.CharMatcher; import com.google.common.base.Strings; import javafx.beans.Observable; import javafx.beans.binding.Bindings; -import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.scene.Group; import javafx.scene.Parent; @@ -25,7 +24,7 @@ import javafx.scene.input.KeyEvent; import javafx.scene.layout.VBox; import javafx.util.StringConverter; import org.apache.commons.lang3.SystemUtils; -import org.cryptomator.common.FxApplicationScoped; +import org.cryptomator.ui.FxApplicationScoped; import org.cryptomator.common.settings.Settings; import org.cryptomator.common.settings.VolumeImpl; import org.cryptomator.ui.l10n.Localization; diff --git a/main/ui/src/main/java/org/cryptomator/ui/controllers/ViewControllerLoader.java b/main/ui/src/main/java/org/cryptomator/ui/controllers/ViewControllerLoader.java index 55f51db83..3e29d0f49 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/controllers/ViewControllerLoader.java +++ b/main/ui/src/main/java/org/cryptomator/ui/controllers/ViewControllerLoader.java @@ -6,7 +6,7 @@ package org.cryptomator.ui.controllers; import javafx.fxml.FXMLLoader; -import org.cryptomator.common.FxApplicationScoped; +import org.cryptomator.ui.FxApplicationScoped; import org.cryptomator.ui.l10n.Localization; import javax.inject.Inject; diff --git a/main/ui/src/main/java/org/cryptomator/ui/controllers/WelcomeController.java b/main/ui/src/main/java/org/cryptomator/ui/controllers/WelcomeController.java index 30d09b972..6e42e8e7a 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/controllers/WelcomeController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/controllers/WelcomeController.java @@ -23,7 +23,7 @@ import javafx.scene.control.Label; import javafx.scene.control.ProgressIndicator; import javafx.scene.layout.VBox; import org.apache.commons.lang3.SystemUtils; -import org.cryptomator.common.FxApplicationScoped; +import org.cryptomator.ui.FxApplicationScoped; import org.cryptomator.common.settings.Settings; import org.cryptomator.ui.l10n.Localization; import org.cryptomator.ui.util.Tasks; diff --git a/main/ui/src/main/java/org/cryptomator/ui/l10n/Localization.java b/main/ui/src/main/java/org/cryptomator/ui/l10n/Localization.java index 565c3d371..edf470d88 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/l10n/Localization.java +++ b/main/ui/src/main/java/org/cryptomator/ui/l10n/Localization.java @@ -7,7 +7,7 @@ package org.cryptomator.ui.l10n; import com.google.common.collect.Sets; import org.apache.commons.lang3.StringUtils; -import org.cryptomator.common.FxApplicationScoped; +import org.cryptomator.ui.FxApplicationScoped; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/main/ui/src/main/java/org/cryptomator/ui/model/AutoUnlocker.java b/main/ui/src/main/java/org/cryptomator/ui/model/AutoUnlocker.java index b2909cb84..235a52b01 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/model/AutoUnlocker.java +++ b/main/ui/src/main/java/org/cryptomator/ui/model/AutoUnlocker.java @@ -5,7 +5,7 @@ *******************************************************************************/ package org.cryptomator.ui.model; -import org.cryptomator.common.FxApplicationScoped; +import org.cryptomator.ui.FxApplicationScoped; import org.cryptomator.cryptolib.api.CryptoException; import org.cryptomator.keychain.KeychainAccess; import org.slf4j.Logger; diff --git a/main/ui/src/main/java/org/cryptomator/ui/model/VaultFactory.java b/main/ui/src/main/java/org/cryptomator/ui/model/VaultFactory.java index 6ee402e88..78351a5fd 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/model/VaultFactory.java +++ b/main/ui/src/main/java/org/cryptomator/ui/model/VaultFactory.java @@ -8,7 +8,7 @@ *******************************************************************************/ package org.cryptomator.ui.model; -import org.cryptomator.common.FxApplicationScoped; +import org.cryptomator.ui.FxApplicationScoped; import org.cryptomator.common.settings.VaultSettings; import javax.inject.Inject; diff --git a/main/ui/src/main/java/org/cryptomator/ui/model/VaultList.java b/main/ui/src/main/java/org/cryptomator/ui/model/VaultList.java index fb9c53afa..f5f7d8be4 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/model/VaultList.java +++ b/main/ui/src/main/java/org/cryptomator/ui/model/VaultList.java @@ -9,7 +9,7 @@ import com.google.common.collect.Lists; import javafx.collections.ListChangeListener; import javafx.collections.ObservableList; import javafx.collections.transformation.TransformationList; -import org.cryptomator.common.FxApplicationScoped; +import org.cryptomator.ui.FxApplicationScoped; import org.cryptomator.common.settings.Settings; import org.cryptomator.common.settings.VaultSettings; diff --git a/main/ui/src/main/java/org/cryptomator/ui/model/WindowsDriveLetters.java b/main/ui/src/main/java/org/cryptomator/ui/model/WindowsDriveLetters.java index 6b8bdef9b..c457deefd 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/model/WindowsDriveLetters.java +++ b/main/ui/src/main/java/org/cryptomator/ui/model/WindowsDriveLetters.java @@ -6,7 +6,7 @@ package org.cryptomator.ui.model; import org.apache.commons.lang3.SystemUtils; -import org.cryptomator.common.FxApplicationScoped; +import org.cryptomator.ui.FxApplicationScoped; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/main/ui/src/main/java/org/cryptomator/ui/model/upgrade/UpgradeStrategies.java b/main/ui/src/main/java/org/cryptomator/ui/model/upgrade/UpgradeStrategies.java index d90a6e5a7..239597e51 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/model/upgrade/UpgradeStrategies.java +++ b/main/ui/src/main/java/org/cryptomator/ui/model/upgrade/UpgradeStrategies.java @@ -5,7 +5,7 @@ *******************************************************************************/ package org.cryptomator.ui.model.upgrade; -import org.cryptomator.common.FxApplicationScoped; +import org.cryptomator.ui.FxApplicationScoped; import org.cryptomator.ui.model.Vault; import javax.inject.Inject; diff --git a/main/ui/src/main/java/org/cryptomator/ui/model/upgrade/UpgradeVersion3DropBundleExtension.java b/main/ui/src/main/java/org/cryptomator/ui/model/upgrade/UpgradeVersion3DropBundleExtension.java index a2456f81f..084296a26 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/model/upgrade/UpgradeVersion3DropBundleExtension.java +++ b/main/ui/src/main/java/org/cryptomator/ui/model/upgrade/UpgradeVersion3DropBundleExtension.java @@ -7,7 +7,7 @@ package org.cryptomator.ui.model.upgrade; import javafx.application.Platform; import org.apache.commons.lang3.StringUtils; -import org.cryptomator.common.FxApplicationScoped; +import org.cryptomator.ui.FxApplicationScoped; import org.cryptomator.cryptolib.Cryptors; import org.cryptomator.cryptolib.api.Cryptor; import org.cryptomator.ui.l10n.Localization; diff --git a/main/ui/src/main/java/org/cryptomator/ui/model/upgrade/UpgradeVersion3to4.java b/main/ui/src/main/java/org/cryptomator/ui/model/upgrade/UpgradeVersion3to4.java index db3350fe8..7bd443a37 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/model/upgrade/UpgradeVersion3to4.java +++ b/main/ui/src/main/java/org/cryptomator/ui/model/upgrade/UpgradeVersion3to4.java @@ -7,7 +7,7 @@ package org.cryptomator.ui.model.upgrade; import com.google.common.io.BaseEncoding; import org.apache.commons.lang3.StringUtils; -import org.cryptomator.common.FxApplicationScoped; +import org.cryptomator.ui.FxApplicationScoped; import org.cryptomator.cryptolib.Cryptors; import org.cryptomator.cryptolib.api.Cryptor; import org.cryptomator.cryptolib.common.MessageDigestSupplier; diff --git a/main/ui/src/main/java/org/cryptomator/ui/model/upgrade/UpgradeVersion4to5.java b/main/ui/src/main/java/org/cryptomator/ui/model/upgrade/UpgradeVersion4to5.java index b64fbdb7f..907154e2e 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/model/upgrade/UpgradeVersion4to5.java +++ b/main/ui/src/main/java/org/cryptomator/ui/model/upgrade/UpgradeVersion4to5.java @@ -5,7 +5,7 @@ *******************************************************************************/ package org.cryptomator.ui.model.upgrade; -import org.cryptomator.common.FxApplicationScoped; +import org.cryptomator.ui.FxApplicationScoped; import org.cryptomator.cryptolib.Cryptors; import org.cryptomator.cryptolib.api.Cryptor; import org.cryptomator.cryptolib.api.FileHeader; diff --git a/main/ui/src/main/java/org/cryptomator/ui/model/upgrade/UpgradeVersion5toX.java b/main/ui/src/main/java/org/cryptomator/ui/model/upgrade/UpgradeVersion5toX.java index 4e0bcfe64..ecc9f1a0c 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/model/upgrade/UpgradeVersion5toX.java +++ b/main/ui/src/main/java/org/cryptomator/ui/model/upgrade/UpgradeVersion5toX.java @@ -5,7 +5,7 @@ *******************************************************************************/ package org.cryptomator.ui.model.upgrade; -import org.cryptomator.common.FxApplicationScoped; +import org.cryptomator.ui.FxApplicationScoped; import org.cryptomator.cryptofs.migration.Migrators; import org.cryptomator.cryptofs.migration.api.NoApplicableMigratorException; import org.cryptomator.cryptolib.Cryptors; diff --git a/main/ui/src/main/java/org/cryptomator/ui/util/PasswordStrengthUtil.java b/main/ui/src/main/java/org/cryptomator/ui/util/PasswordStrengthUtil.java index 373f698d2..dea9114eb 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/util/PasswordStrengthUtil.java +++ b/main/ui/src/main/java/org/cryptomator/ui/util/PasswordStrengthUtil.java @@ -15,7 +15,7 @@ import javafx.scene.layout.Background; import javafx.scene.layout.BackgroundFill; import javafx.scene.layout.CornerRadii; import javafx.scene.paint.Color; -import org.cryptomator.common.FxApplicationScoped; +import org.cryptomator.ui.FxApplicationScoped; import org.cryptomator.ui.l10n.Localization; import javax.inject.Inject; From 180c07cf61d2de274a1ea5b15fcfbb2036e6b57a Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Thu, 11 Jul 2019 00:19:18 +0200 Subject: [PATCH 002/264] new class layout for viewcontrollers --- main/pom.xml | 6 ++ main/ui/pom.xml | 4 ++ .../org/cryptomator/ui/FXMLLoaderFactory.java | 46 ++++++++++++++++ .../org/cryptomator/ui/FxApplication.java | 28 ++++++---- .../cryptomator/ui/FxApplicationModule.java | 2 + .../java/org/cryptomator/ui/FxController.java | 9 +++ .../org/cryptomator/ui/FxControllerKey.java | 24 ++++++++ .../java/org/cryptomator/ui/UiModule.java | 4 +- .../ui/mainwindow/MainWindowController.java | 55 +++++++++++++++++++ .../ui/mainwindow/MainWindowModule.java | 18 ++++++ .../ui/vaultlist/VaultListController.java | 25 +++++++++ .../ui/vaultlist/VaultListModule.java | 17 ++++++ .../src/main/resources/fxml/main_window.fxml | 38 +++++++++++++ .../ui/src/main/resources/fxml/vaultlist.fxml | 9 +++ .../main/resources/i18n/strings.properties | 3 + .../main/resources/i18n/strings_de.properties | 3 + .../main/resources/i18n/strings_en.properties | 3 + 17 files changed, 282 insertions(+), 12 deletions(-) create mode 100644 main/ui/src/main/java/org/cryptomator/ui/FXMLLoaderFactory.java create mode 100644 main/ui/src/main/java/org/cryptomator/ui/FxController.java create mode 100644 main/ui/src/main/java/org/cryptomator/ui/FxControllerKey.java create mode 100644 main/ui/src/main/java/org/cryptomator/ui/mainwindow/MainWindowController.java create mode 100644 main/ui/src/main/java/org/cryptomator/ui/mainwindow/MainWindowModule.java create mode 100644 main/ui/src/main/java/org/cryptomator/ui/vaultlist/VaultListController.java create mode 100644 main/ui/src/main/java/org/cryptomator/ui/vaultlist/VaultListModule.java create mode 100644 main/ui/src/main/resources/fxml/main_window.fxml create mode 100644 main/ui/src/main/resources/fxml/vaultlist.fxml create mode 100644 main/ui/src/main/resources/i18n/strings.properties create mode 100644 main/ui/src/main/resources/i18n/strings_de.properties create mode 100644 main/ui/src/main/resources/i18n/strings_en.properties diff --git a/main/pom.xml b/main/pom.xml index ad93007b5..0bd97ed7b 100644 --- a/main/pom.xml +++ b/main/pom.xml @@ -32,6 +32,7 @@ 1.0.10 12 + 4.7.0-9.1.2 2.6 3.8.1 @@ -139,6 +140,11 @@ javafx-fxml ${javafx.version} + + de.jensd + fontawesomefx-fontawesome + ${fontawesomefx.version} + diff --git a/main/ui/pom.xml b/main/ui/pom.xml index 1465683f0..bf8e89ce1 100644 --- a/main/ui/pom.xml +++ b/main/ui/pom.xml @@ -55,6 +55,10 @@ org.openjfx javafx-fxml + + de.jensd + fontawesomefx-fontawesome + diff --git a/main/ui/src/main/java/org/cryptomator/ui/FXMLLoaderFactory.java b/main/ui/src/main/java/org/cryptomator/ui/FXMLLoaderFactory.java new file mode 100644 index 000000000..146d16ae4 --- /dev/null +++ b/main/ui/src/main/java/org/cryptomator/ui/FXMLLoaderFactory.java @@ -0,0 +1,46 @@ +package org.cryptomator.ui; + +import javafx.fxml.FXMLLoader; + +import javax.inject.Inject; +import javax.inject.Provider; +import java.io.IOException; +import java.io.InputStream; +import java.util.Map; +import java.util.ResourceBundle; + +@FxApplicationScoped +public class FXMLLoaderFactory { + + private final Map, Provider> factories; + private final ResourceBundle resourceBundle; + + @Inject + FXMLLoaderFactory(Map, Provider> factories) { + this.factories = factories; + this.resourceBundle = ResourceBundle.getBundle("i18n.strings"); + } + + public FXMLLoader construct() { + FXMLLoader loader = new FXMLLoader(); + loader.setControllerFactory(this::constructController); + loader.setResources(resourceBundle); + return loader; + } + + public FXMLLoader load(String fxmlResourceName) throws IOException { + FXMLLoader loader = construct(); + try (InputStream in = getClass().getResourceAsStream(fxmlResourceName)) { + loader.load(in); + } + return loader; + } + + private FxController constructController(Class aClass) { + if (!factories.containsKey(aClass)) { + throw new IllegalArgumentException("ViewController not registered: " + aClass); + } else { + return factories.get(aClass).get(); + } + } +} diff --git a/main/ui/src/main/java/org/cryptomator/ui/FxApplication.java b/main/ui/src/main/java/org/cryptomator/ui/FxApplication.java index f8136479f..8ffff75cd 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/FxApplication.java +++ b/main/ui/src/main/java/org/cryptomator/ui/FxApplication.java @@ -1,14 +1,16 @@ package org.cryptomator.ui; import javafx.application.Application; +import javafx.scene.Parent; +import javafx.scene.Scene; import javafx.stage.Stage; -import org.cryptomator.ui.controllers.MainController; -import org.cryptomator.ui.controllers.ViewControllerLoader; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.inject.Inject; import javax.inject.Named; +import java.io.IOException; +import java.io.UncheckedIOException; @FxApplicationScoped public class FxApplication extends Application { @@ -16,24 +18,28 @@ public class FxApplication extends Application { private static final Logger LOG = LoggerFactory.getLogger(FxApplication.class); private final Stage primaryStage; - private final ViewControllerLoader fxmlLoader; + private final FXMLLoaderFactory fxmlLoaders; @Inject - FxApplication(@Named("mainWindow") Stage primaryStage, ViewControllerLoader fxmlLoader) { + FxApplication(@Named("mainWindow") Stage primaryStage, FXMLLoaderFactory fxmlLoaders) { this.primaryStage = primaryStage; - this.fxmlLoader = fxmlLoader; + this.fxmlLoaders = fxmlLoaders; } public void start() { - LOG.info("Starting GUI..."); - start(primaryStage); + try { + LOG.info("Starting GUI..."); + start(primaryStage); + } catch (IOException e) { + throw new UncheckedIOException(e); + } } @Override - public void start(Stage primaryStage) { - MainController mainCtrl = fxmlLoader.load("/fxml/main.fxml"); - mainCtrl.initStage(primaryStage); - primaryStage.show(); + public void start(Stage stage) throws IOException { + Parent root = fxmlLoaders.load("/fxml/main_window.fxml").getRoot(); + stage.setScene(new Scene(root)); + stage.show(); } } diff --git a/main/ui/src/main/java/org/cryptomator/ui/FxApplicationModule.java b/main/ui/src/main/java/org/cryptomator/ui/FxApplicationModule.java index 5482dd189..658204c9b 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/FxApplicationModule.java +++ b/main/ui/src/main/java/org/cryptomator/ui/FxApplicationModule.java @@ -10,6 +10,7 @@ import dagger.Module; import dagger.Provides; import javafx.application.Application; import javafx.stage.Stage; +import javafx.stage.StageStyle; import javax.inject.Named; @@ -23,6 +24,7 @@ abstract class FxApplicationModule { Stage stage = new Stage(); stage.setMinWidth(652.0); stage.setMinHeight(440.0); + stage.initStyle(StageStyle.UNDECORATED); return stage; } diff --git a/main/ui/src/main/java/org/cryptomator/ui/FxController.java b/main/ui/src/main/java/org/cryptomator/ui/FxController.java new file mode 100644 index 000000000..df717a5b2 --- /dev/null +++ b/main/ui/src/main/java/org/cryptomator/ui/FxController.java @@ -0,0 +1,9 @@ +/******************************************************************************* + * 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; + +public interface FxController { +} diff --git a/main/ui/src/main/java/org/cryptomator/ui/FxControllerKey.java b/main/ui/src/main/java/org/cryptomator/ui/FxControllerKey.java new file mode 100644 index 000000000..a9cfbf739 --- /dev/null +++ b/main/ui/src/main/java/org/cryptomator/ui/FxControllerKey.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * 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; + +import dagger.MapKey; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +// TODO rename after refactoring +@Documented +@Target(METHOD) +@Retention(RUNTIME) +@MapKey +public @interface FxControllerKey { + Class value(); +} diff --git a/main/ui/src/main/java/org/cryptomator/ui/UiModule.java b/main/ui/src/main/java/org/cryptomator/ui/UiModule.java index 6c09147e1..59d652cc1 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/UiModule.java +++ b/main/ui/src/main/java/org/cryptomator/ui/UiModule.java @@ -16,7 +16,9 @@ import org.cryptomator.common.settings.Settings; import org.cryptomator.frontend.webdav.WebDavServer; import org.cryptomator.keychain.KeychainModule; import org.cryptomator.ui.controllers.ViewControllerModule; +import org.cryptomator.ui.mainwindow.MainWindowModule; import org.cryptomator.ui.model.VaultComponent; +import org.cryptomator.ui.vaultlist.VaultListModule; import org.fxmisc.easybind.EasyBind; import javax.inject.Named; @@ -27,7 +29,7 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Consumer; -@Module(includes = {ViewControllerModule.class, KeychainModule.class}, subcomponents = {VaultComponent.class}) +@Module(includes = {ViewControllerModule.class, KeychainModule.class, VaultListModule.class, MainWindowModule.class}, subcomponents = {VaultComponent.class}) public class UiModule { private static final int NUM_SCHEDULER_THREADS = 4; diff --git a/main/ui/src/main/java/org/cryptomator/ui/mainwindow/MainWindowController.java b/main/ui/src/main/java/org/cryptomator/ui/mainwindow/MainWindowController.java new file mode 100644 index 000000000..3a9cbc828 --- /dev/null +++ b/main/ui/src/main/java/org/cryptomator/ui/mainwindow/MainWindowController.java @@ -0,0 +1,55 @@ +package org.cryptomator.ui.mainwindow; + +import javafx.application.Application; +import javafx.fxml.FXML; +import javafx.scene.layout.HBox; +import javafx.stage.Stage; +import org.cryptomator.ui.FxApplicationScoped; +import org.cryptomator.ui.FxController; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.inject.Inject; +import javax.inject.Named; +import java.util.concurrent.CountDownLatch; + +@FxApplicationScoped +public class MainWindowController implements FxController { + + private static final Logger LOG = LoggerFactory.getLogger(MainWindowController.class); + + private final CountDownLatch shutdownLatch; + private final Stage mainWindow; + + @FXML + public HBox titleBar; + + private double xOffset; + private double yOffset; + + @Inject + public MainWindowController(@Named("shutdownLatch") CountDownLatch shutdownLatch, @Named("mainWindow") Stage mainWindow) { + this.shutdownLatch = shutdownLatch; + this.mainWindow = mainWindow; + } + + @FXML + public void initialize() { + LOG.debug("init MainWindowController"); + titleBar.setOnMousePressed(event -> { + xOffset = event.getSceneX(); + yOffset = event.getSceneY(); + }); + titleBar.setOnMouseDragged(event -> { + titleBar.getScene().getWindow().setX(event.getScreenX() - xOffset); + titleBar.getScene().getWindow().setY(event.getScreenY() - yOffset); + }); + } + + @FXML + public void close() { + mainWindow.close(); + LOG.info("closed..."); + shutdownLatch.countDown(); + } +} diff --git a/main/ui/src/main/java/org/cryptomator/ui/mainwindow/MainWindowModule.java b/main/ui/src/main/java/org/cryptomator/ui/mainwindow/MainWindowModule.java new file mode 100644 index 000000000..6a0344ee1 --- /dev/null +++ b/main/ui/src/main/java/org/cryptomator/ui/mainwindow/MainWindowModule.java @@ -0,0 +1,18 @@ +package org.cryptomator.ui.mainwindow; + +import dagger.Binds; +import dagger.Module; +import dagger.multibindings.IntoMap; +import org.cryptomator.ui.FxController; +import org.cryptomator.ui.FxControllerKey; +import org.cryptomator.ui.vaultlist.VaultListController; + +@Module +public abstract class MainWindowModule { + + @Binds + @IntoMap + @FxControllerKey(MainWindowController.class) + abstract FxController bindController(MainWindowController controller); + +} diff --git a/main/ui/src/main/java/org/cryptomator/ui/vaultlist/VaultListController.java b/main/ui/src/main/java/org/cryptomator/ui/vaultlist/VaultListController.java new file mode 100644 index 000000000..9e28ba9c5 --- /dev/null +++ b/main/ui/src/main/java/org/cryptomator/ui/vaultlist/VaultListController.java @@ -0,0 +1,25 @@ +package org.cryptomator.ui.vaultlist; + +import javafx.fxml.FXML; +import org.cryptomator.ui.FxApplicationScoped; +import org.cryptomator.ui.FxController; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.inject.Inject; + +@FxApplicationScoped +public class VaultListController implements FxController { + + private static final Logger LOG = LoggerFactory.getLogger(VaultListController.class); + + @Inject + public VaultListController() { + } + + @FXML + public void initialize() { + LOG.debug("init VaultListController"); + } + +} diff --git a/main/ui/src/main/java/org/cryptomator/ui/vaultlist/VaultListModule.java b/main/ui/src/main/java/org/cryptomator/ui/vaultlist/VaultListModule.java new file mode 100644 index 000000000..86ce99080 --- /dev/null +++ b/main/ui/src/main/java/org/cryptomator/ui/vaultlist/VaultListModule.java @@ -0,0 +1,17 @@ +package org.cryptomator.ui.vaultlist; + +import dagger.Binds; +import dagger.Module; +import dagger.multibindings.IntoMap; +import org.cryptomator.ui.FxController; +import org.cryptomator.ui.FxControllerKey; + +@Module +public abstract class VaultListModule { + + @Binds + @IntoMap + @FxControllerKey(VaultListController.class) + abstract FxController bindController(VaultListController controller); + +} diff --git a/main/ui/src/main/resources/fxml/main_window.fxml b/main/ui/src/main/resources/fxml/main_window.fxml new file mode 100644 index 000000000..d0730d023 --- /dev/null +++ b/main/ui/src/main/resources/fxml/main_window.fxml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/main/ui/src/main/resources/fxml/vaultlist.fxml b/main/ui/src/main/resources/fxml/vaultlist.fxml new file mode 100644 index 000000000..344ceade7 --- /dev/null +++ b/main/ui/src/main/resources/fxml/vaultlist.fxml @@ -0,0 +1,9 @@ + + + + + + diff --git a/main/ui/src/main/resources/i18n/strings.properties b/main/ui/src/main/resources/i18n/strings.properties new file mode 100644 index 000000000..99c76666b --- /dev/null +++ b/main/ui/src/main/resources/i18n/strings.properties @@ -0,0 +1,3 @@ +main.closeBtn.tooltip=Close +main.settingsBtn.tooltip=Settings +title=Cryptomator \ No newline at end of file diff --git a/main/ui/src/main/resources/i18n/strings_de.properties b/main/ui/src/main/resources/i18n/strings_de.properties new file mode 100644 index 000000000..3f4eb3198 --- /dev/null +++ b/main/ui/src/main/resources/i18n/strings_de.properties @@ -0,0 +1,3 @@ +main.closeBtn.tooltip=Close +main.settingsBtn.tooltip=Settings +title=CryptomatorDE \ No newline at end of file diff --git a/main/ui/src/main/resources/i18n/strings_en.properties b/main/ui/src/main/resources/i18n/strings_en.properties new file mode 100644 index 000000000..8c23b81fa --- /dev/null +++ b/main/ui/src/main/resources/i18n/strings_en.properties @@ -0,0 +1,3 @@ +main.closeBtn.tooltip=Close +main.settingsBtn.tooltip=Settings +title=CryptomatorEN \ No newline at end of file From cfea1c16bc8f46eb5264a8c604519ae00969d206 Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Mon, 15 Jul 2019 11:32:49 +0200 Subject: [PATCH 003/264] added vault list and vault detail view --- .idea/compiler.xml | 5 +- .idea/modules.xml | 1 - .../org/cryptomator/launcher/Cryptomator.java | 6 +- .../ui/FxApplicationComponent.java | 9 +++ .../java/org/cryptomator/ui/UiModule.java | 4 +- .../ui/mainwindow/MainWindowModule.java | 31 +++++++++- .../ui/mainwindow/VaultDetailController.java | 32 +++++++++++ .../ui/mainwindow/VaultListController.java | 47 ++++++++++++++++ .../ui/vaultlist/VaultListController.java | 25 --------- .../ui/vaultlist/VaultListModule.java | 17 ------ .../src/main/resources/fxml/main_window.fxml | 56 ++++++++++--------- .../src/main/resources/fxml/vault_detail.fxml | 16 ++++++ .../src/main/resources/fxml/vault_list.fxml | 49 ++++++++++++++++ .../ui/src/main/resources/fxml/vaultlist.fxml | 9 --- .../main/resources/i18n/strings.properties | 2 +- .../main/resources/i18n/strings_de.properties | 2 +- .../main/resources/i18n/strings_en.properties | 2 +- 17 files changed, 217 insertions(+), 96 deletions(-) create mode 100644 main/ui/src/main/java/org/cryptomator/ui/mainwindow/VaultDetailController.java create mode 100644 main/ui/src/main/java/org/cryptomator/ui/mainwindow/VaultListController.java delete mode 100644 main/ui/src/main/java/org/cryptomator/ui/vaultlist/VaultListController.java delete mode 100644 main/ui/src/main/java/org/cryptomator/ui/vaultlist/VaultListModule.java create mode 100644 main/ui/src/main/resources/fxml/vault_detail.fxml create mode 100644 main/ui/src/main/resources/fxml/vault_list.fxml delete mode 100644 main/ui/src/main/resources/fxml/vaultlist.fxml diff --git a/.idea/compiler.xml b/.idea/compiler.xml index ace983167..da1897030 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -23,14 +23,11 @@ - + - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml index bca3878d6..2e793ed5c 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -3,7 +3,6 @@ - \ No newline at end of file diff --git a/main/launcher/src/main/java/org/cryptomator/launcher/Cryptomator.java b/main/launcher/src/main/java/org/cryptomator/launcher/Cryptomator.java index 71f43a100..30156ea0c 100644 --- a/main/launcher/src/main/java/org/cryptomator/launcher/Cryptomator.java +++ b/main/launcher/src/main/java/org/cryptomator/launcher/Cryptomator.java @@ -89,11 +89,7 @@ public class Cryptomator { private int runGuiApplication() { try { shutdownPerformer.registerShutdownHook(); - Platform.startup(() -> { - assert Platform.isFxApplicationThread(); - FxApplication app = CRYPTOMATOR_COMPONENT.fxApplicationComponent().application(); - app.start(); - }); + CRYPTOMATOR_COMPONENT.fxApplicationComponent().start(); shutdownLatch.await(); LOG.info("UI shut down"); return 0; diff --git a/main/ui/src/main/java/org/cryptomator/ui/FxApplicationComponent.java b/main/ui/src/main/java/org/cryptomator/ui/FxApplicationComponent.java index 5b029a50c..ac000565c 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/FxApplicationComponent.java +++ b/main/ui/src/main/java/org/cryptomator/ui/FxApplicationComponent.java @@ -6,11 +6,20 @@ package org.cryptomator.ui; import dagger.Subcomponent; +import javafx.application.Application; +import javafx.application.Platform; @FxApplicationScoped @Subcomponent(modules = FxApplicationModule.class) public interface FxApplicationComponent { FxApplication application(); + + default void start() { + Platform.startup(() -> { + assert Platform.isFxApplicationThread(); + application().start(); + }); + } } diff --git a/main/ui/src/main/java/org/cryptomator/ui/UiModule.java b/main/ui/src/main/java/org/cryptomator/ui/UiModule.java index 59d652cc1..8447916f6 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/UiModule.java +++ b/main/ui/src/main/java/org/cryptomator/ui/UiModule.java @@ -15,10 +15,8 @@ import org.apache.commons.lang3.SystemUtils; import org.cryptomator.common.settings.Settings; import org.cryptomator.frontend.webdav.WebDavServer; import org.cryptomator.keychain.KeychainModule; -import org.cryptomator.ui.controllers.ViewControllerModule; import org.cryptomator.ui.mainwindow.MainWindowModule; import org.cryptomator.ui.model.VaultComponent; -import org.cryptomator.ui.vaultlist.VaultListModule; import org.fxmisc.easybind.EasyBind; import javax.inject.Named; @@ -29,7 +27,7 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Consumer; -@Module(includes = {ViewControllerModule.class, KeychainModule.class, VaultListModule.class, MainWindowModule.class}, subcomponents = {VaultComponent.class}) +@Module(includes = {KeychainModule.class, MainWindowModule.class}, subcomponents = {VaultComponent.class}) public class UiModule { private static final int NUM_SCHEDULER_THREADS = 4; diff --git a/main/ui/src/main/java/org/cryptomator/ui/mainwindow/MainWindowModule.java b/main/ui/src/main/java/org/cryptomator/ui/mainwindow/MainWindowModule.java index 6a0344ee1..c2b2ae5b3 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/mainwindow/MainWindowModule.java +++ b/main/ui/src/main/java/org/cryptomator/ui/mainwindow/MainWindowModule.java @@ -2,10 +2,16 @@ package org.cryptomator.ui.mainwindow; import dagger.Binds; import dagger.Module; +import dagger.Provides; import dagger.multibindings.IntoMap; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.SimpleObjectProperty; +import javafx.collections.ObservableList; +import org.cryptomator.ui.FxApplicationScoped; import org.cryptomator.ui.FxController; import org.cryptomator.ui.FxControllerKey; -import org.cryptomator.ui.vaultlist.VaultListController; +import org.cryptomator.ui.model.Vault; +import org.cryptomator.ui.model.VaultList; @Module public abstract class MainWindowModule { @@ -13,6 +19,27 @@ public abstract class MainWindowModule { @Binds @IntoMap @FxControllerKey(MainWindowController.class) - abstract FxController bindController(MainWindowController controller); + abstract FxController bindMainWindowController(MainWindowController controller); + + @Binds + @IntoMap + @FxControllerKey(VaultListController.class) + abstract FxController bindVaultListController(VaultListController controller); + + @Binds + @IntoMap + @FxControllerKey(VaultDetailController.class) + abstract FxController bindVaultDetailController(VaultDetailController controller); + + // ------------------ + + @Binds + abstract ObservableList provideVaults(VaultList vaultList); + + @Provides + @FxApplicationScoped + static ObjectProperty provideSelectedVault() { + return new SimpleObjectProperty<>(); + } } diff --git a/main/ui/src/main/java/org/cryptomator/ui/mainwindow/VaultDetailController.java b/main/ui/src/main/java/org/cryptomator/ui/mainwindow/VaultDetailController.java new file mode 100644 index 000000000..580a9a825 --- /dev/null +++ b/main/ui/src/main/java/org/cryptomator/ui/mainwindow/VaultDetailController.java @@ -0,0 +1,32 @@ +package org.cryptomator.ui.mainwindow; + +import javafx.beans.property.ObjectProperty; +import org.cryptomator.ui.FxApplicationScoped; +import org.cryptomator.ui.FxController; +import org.cryptomator.ui.model.Vault; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.inject.Inject; + +@FxApplicationScoped +public class VaultDetailController implements FxController { + + private static final Logger LOG = LoggerFactory.getLogger(VaultDetailController.class); + + private final ObjectProperty vault; + + @Inject + VaultDetailController(ObjectProperty vault) { + this.vault = vault; + } + + public ObjectProperty vaultProperty() { + return vault; + } + + public Vault getVault() { + return vault.get(); + } + +} diff --git a/main/ui/src/main/java/org/cryptomator/ui/mainwindow/VaultListController.java b/main/ui/src/main/java/org/cryptomator/ui/mainwindow/VaultListController.java new file mode 100644 index 000000000..e3e790663 --- /dev/null +++ b/main/ui/src/main/java/org/cryptomator/ui/mainwindow/VaultListController.java @@ -0,0 +1,47 @@ +package org.cryptomator.ui.mainwindow; + +import javafx.beans.binding.Bindings; +import javafx.beans.property.ObjectProperty; +import javafx.collections.ObservableList; +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.scene.control.ListView; +import javafx.scene.layout.AnchorPane; +import org.cryptomator.ui.FxApplicationScoped; +import org.cryptomator.ui.FxController; +import org.cryptomator.ui.model.Vault; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.inject.Inject; + +@FxApplicationScoped +public class VaultListController implements FxController { + + private static final Logger LOG = LoggerFactory.getLogger(VaultListController.class); + + private final ObservableList vaults; + private final ObjectProperty selectedVault; + public ListView vaultList; + public AnchorPane onboardingOverlay; + + @Inject + public VaultListController(ObservableList vaults, ObjectProperty selectedVault) { + this.vaults = vaults; + this.selectedVault = selectedVault; + } + + @FXML + public void initialize() { + LOG.debug("init VaultListController"); + onboardingOverlay.visibleProperty().bind(Bindings.isEmpty(vaults)); + vaultList.setItems(vaults); + selectedVault.bind(vaultList.getSelectionModel().selectedItemProperty()); + } + + public void didClickAddVault(ActionEvent actionEvent) { + } + + public void didClickRemoveVault(ActionEvent actionEvent) { + } +} diff --git a/main/ui/src/main/java/org/cryptomator/ui/vaultlist/VaultListController.java b/main/ui/src/main/java/org/cryptomator/ui/vaultlist/VaultListController.java deleted file mode 100644 index 9e28ba9c5..000000000 --- a/main/ui/src/main/java/org/cryptomator/ui/vaultlist/VaultListController.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.cryptomator.ui.vaultlist; - -import javafx.fxml.FXML; -import org.cryptomator.ui.FxApplicationScoped; -import org.cryptomator.ui.FxController; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.inject.Inject; - -@FxApplicationScoped -public class VaultListController implements FxController { - - private static final Logger LOG = LoggerFactory.getLogger(VaultListController.class); - - @Inject - public VaultListController() { - } - - @FXML - public void initialize() { - LOG.debug("init VaultListController"); - } - -} diff --git a/main/ui/src/main/java/org/cryptomator/ui/vaultlist/VaultListModule.java b/main/ui/src/main/java/org/cryptomator/ui/vaultlist/VaultListModule.java deleted file mode 100644 index 86ce99080..000000000 --- a/main/ui/src/main/java/org/cryptomator/ui/vaultlist/VaultListModule.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.cryptomator.ui.vaultlist; - -import dagger.Binds; -import dagger.Module; -import dagger.multibindings.IntoMap; -import org.cryptomator.ui.FxController; -import org.cryptomator.ui.FxControllerKey; - -@Module -public abstract class VaultListModule { - - @Binds - @IntoMap - @FxControllerKey(VaultListController.class) - abstract FxController bindController(VaultListController controller); - -} diff --git a/main/ui/src/main/resources/fxml/main_window.fxml b/main/ui/src/main/resources/fxml/main_window.fxml index d0730d023..547d7d3d0 100644 --- a/main/ui/src/main/resources/fxml/main_window.fxml +++ b/main/ui/src/main/resources/fxml/main_window.fxml @@ -8,31 +8,33 @@ - - - - - - - - - - - - + fx:controller="org.cryptomator.ui.mainwindow.MainWindowController" + styleClass="main-window"> + + + + + + + + + + + + + diff --git a/main/ui/src/main/resources/fxml/vault_detail.fxml b/main/ui/src/main/resources/fxml/vault_detail.fxml new file mode 100644 index 000000000..6a301e1a3 --- /dev/null +++ b/main/ui/src/main/resources/fxml/vault_detail.fxml @@ -0,0 +1,16 @@ + + + + + + + + + + + + diff --git a/main/ui/src/main/resources/fxml/vault_list.fxml b/main/ui/src/main/resources/fxml/vault_list.fxml new file mode 100644 index 000000000..1dbd23c1e --- /dev/null +++ b/main/ui/src/main/resources/fxml/vault_list.fxml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/main/ui/src/main/resources/fxml/vaultlist.fxml b/main/ui/src/main/resources/fxml/vaultlist.fxml deleted file mode 100644 index 344ceade7..000000000 --- a/main/ui/src/main/resources/fxml/vaultlist.fxml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - diff --git a/main/ui/src/main/resources/i18n/strings.properties b/main/ui/src/main/resources/i18n/strings.properties index 99c76666b..d47a4cb32 100644 --- a/main/ui/src/main/resources/i18n/strings.properties +++ b/main/ui/src/main/resources/i18n/strings.properties @@ -1,3 +1,3 @@ main.closeBtn.tooltip=Close main.settingsBtn.tooltip=Settings -title=Cryptomator \ No newline at end of file +vaultlist.emptyList.onboardingInstruction=Click here to add a vault \ No newline at end of file diff --git a/main/ui/src/main/resources/i18n/strings_de.properties b/main/ui/src/main/resources/i18n/strings_de.properties index 3f4eb3198..131176730 100644 --- a/main/ui/src/main/resources/i18n/strings_de.properties +++ b/main/ui/src/main/resources/i18n/strings_de.properties @@ -1,3 +1,3 @@ main.closeBtn.tooltip=Close main.settingsBtn.tooltip=Settings -title=CryptomatorDE \ No newline at end of file +vaultlist.emptyList.onboardingInstruction=Klicken Sie hier, um neue Tresore hinzuzufügen \ No newline at end of file diff --git a/main/ui/src/main/resources/i18n/strings_en.properties b/main/ui/src/main/resources/i18n/strings_en.properties index 8c23b81fa..d47a4cb32 100644 --- a/main/ui/src/main/resources/i18n/strings_en.properties +++ b/main/ui/src/main/resources/i18n/strings_en.properties @@ -1,3 +1,3 @@ main.closeBtn.tooltip=Close main.settingsBtn.tooltip=Settings -title=CryptomatorEN \ No newline at end of file +vaultlist.emptyList.onboardingInstruction=Click here to add a vault \ No newline at end of file From 52a9a2f0188ab9742a8bac1ea37c546569a0be2f Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Mon, 15 Jul 2019 11:32:58 +0200 Subject: [PATCH 004/264] starting with blank css --- .../ui/FxApplicationComponent.java | 1 + main/ui/src/main/resources/css/theme.css | 34 +++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 main/ui/src/main/resources/css/theme.css diff --git a/main/ui/src/main/java/org/cryptomator/ui/FxApplicationComponent.java b/main/ui/src/main/java/org/cryptomator/ui/FxApplicationComponent.java index ac000565c..165b143ea 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/FxApplicationComponent.java +++ b/main/ui/src/main/java/org/cryptomator/ui/FxApplicationComponent.java @@ -18,6 +18,7 @@ public interface FxApplicationComponent { default void start() { Platform.startup(() -> { assert Platform.isFxApplicationThread(); + Application.setUserAgentStylesheet(getClass().getResource("/css/theme.css").toString()); application().start(); }); } diff --git a/main/ui/src/main/resources/css/theme.css b/main/ui/src/main/resources/css/theme.css new file mode 100644 index 000000000..1743598b8 --- /dev/null +++ b/main/ui/src/main/resources/css/theme.css @@ -0,0 +1,34 @@ +/******************************************************************************* + * * + * COLORS * + * * + ******************************************************************************/ + +.root { + WHITE: #FFF; + PRIMARY_BG: #79B01A; +} + + +/******************************************************************************* + * * + * Main Window * + * * + ******************************************************************************/ + +.main-window .title { + -fx-background-color: PRIMARY_BG; +} + + +/******************************************************************************* + * * + * Tooltip * + * * + ******************************************************************************/ + +.tooltip { + -fx-background-color: WHITE; + -fx-padding: 0.2em 0.4em 0.2em 0.4em; + -fx-font-size: 0.8em; +} \ No newline at end of file From a3382c2d5b375e770c8e23f3ef2bf16064243458 Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Mon, 15 Jul 2019 16:39:21 +0200 Subject: [PATCH 005/264] hook up preferences window --- .../org/cryptomator/ui/FxApplication.java | 53 ++++++++++++++----- .../cryptomator/ui/FxApplicationModule.java | 11 +--- .../java/org/cryptomator/ui/UiModule.java | 3 +- .../cryptomator/ui/mainwindow/MainWindow.java | 13 +++++ .../ui/mainwindow/MainWindowController.java | 12 ++++- .../ui/mainwindow/MainWindowModule.java | 15 +++++- .../ui/preferences/PreferencesController.java | 13 +++++ .../ui/preferences/PreferencesModule.java | 34 ++++++++++++ .../ui/preferences/PreferencesWindow.java | 13 +++++ .../src/main/resources/fxml/main_window.fxml | 2 +- .../src/main/resources/fxml/preferences.fxml | 10 ++++ 11 files changed, 151 insertions(+), 28 deletions(-) create mode 100644 main/ui/src/main/java/org/cryptomator/ui/mainwindow/MainWindow.java create mode 100644 main/ui/src/main/java/org/cryptomator/ui/preferences/PreferencesController.java create mode 100644 main/ui/src/main/java/org/cryptomator/ui/preferences/PreferencesModule.java create mode 100644 main/ui/src/main/java/org/cryptomator/ui/preferences/PreferencesWindow.java create mode 100644 main/ui/src/main/resources/fxml/preferences.fxml diff --git a/main/ui/src/main/java/org/cryptomator/ui/FxApplication.java b/main/ui/src/main/java/org/cryptomator/ui/FxApplication.java index 8ffff75cd..41973dc57 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/FxApplication.java +++ b/main/ui/src/main/java/org/cryptomator/ui/FxApplication.java @@ -1,14 +1,18 @@ package org.cryptomator.ui; import javafx.application.Application; +import javafx.application.Platform; import javafx.scene.Parent; import javafx.scene.Scene; import javafx.stage.Stage; +import org.cryptomator.ui.mainwindow.MainWindow; +import org.cryptomator.ui.preferences.PreferencesWindow; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.inject.Inject; -import javax.inject.Named; +import java.awt.Desktop; +import java.awt.desktop.PreferencesEvent; import java.io.IOException; import java.io.UncheckedIOException; @@ -17,29 +21,52 @@ public class FxApplication extends Application { private static final Logger LOG = LoggerFactory.getLogger(FxApplication.class); - private final Stage primaryStage; + private final Stage mainWindow; + private final Stage preferencesWindow; private final FXMLLoaderFactory fxmlLoaders; @Inject - FxApplication(@Named("mainWindow") Stage primaryStage, FXMLLoaderFactory fxmlLoaders) { - this.primaryStage = primaryStage; + FxApplication(@MainWindow Stage mainWindow, @PreferencesWindow Stage preferencesWindow, FXMLLoaderFactory fxmlLoaders) { + this.mainWindow = mainWindow; + this.preferencesWindow = preferencesWindow; this.fxmlLoaders = fxmlLoaders; } public void start() { - try { - LOG.info("Starting GUI..."); - start(primaryStage); - } catch (IOException e) { - throw new UncheckedIOException(e); + LOG.trace("FxApplication.start()"); + if (Desktop.getDesktop().isSupported(Desktop.Action.APP_PREFERENCES)) { + Desktop.getDesktop().setPreferencesHandler(this::handlePreferences); } + + start(mainWindow); } @Override - public void start(Stage stage) throws IOException { - Parent root = fxmlLoaders.load("/fxml/main_window.fxml").getRoot(); - stage.setScene(new Scene(root)); - stage.show(); + public void start(Stage stage) { + assert stage == mainWindow; + showMainWindow(); + } + + private void handlePreferences(PreferencesEvent preferencesEvent) { + Platform.runLater(this::showPreferencesWindow); + } + + public void showMainWindow() { + showViewInWindow("/fxml/main_window.fxml", mainWindow); + } + + public void showPreferencesWindow() { + showViewInWindow("/fxml/preferences.fxml", preferencesWindow); + } + + private void showViewInWindow(String fxmlResourceName, Stage window) { + try { + Parent root = fxmlLoaders.load(fxmlResourceName).getRoot(); + window.setScene(new Scene(root)); + window.show(); + } catch (IOException e) { + LOG.error("Failed to load " + fxmlResourceName, e); + } } } diff --git a/main/ui/src/main/java/org/cryptomator/ui/FxApplicationModule.java b/main/ui/src/main/java/org/cryptomator/ui/FxApplicationModule.java index 658204c9b..a57e09ec5 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/FxApplicationModule.java +++ b/main/ui/src/main/java/org/cryptomator/ui/FxApplicationModule.java @@ -17,16 +17,7 @@ import javax.inject.Named; @Module(includes = {UiModule.class}) abstract class FxApplicationModule { - @Provides - @FxApplicationScoped - @Named("mainWindow") - static Stage providePrimaryStage() { - Stage stage = new Stage(); - stage.setMinWidth(652.0); - stage.setMinHeight(440.0); - stage.initStyle(StageStyle.UNDECORATED); - return stage; - } + @Binds @FxApplicationScoped diff --git a/main/ui/src/main/java/org/cryptomator/ui/UiModule.java b/main/ui/src/main/java/org/cryptomator/ui/UiModule.java index 8447916f6..9b9922061 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/UiModule.java +++ b/main/ui/src/main/java/org/cryptomator/ui/UiModule.java @@ -17,6 +17,7 @@ import org.cryptomator.frontend.webdav.WebDavServer; import org.cryptomator.keychain.KeychainModule; import org.cryptomator.ui.mainwindow.MainWindowModule; import org.cryptomator.ui.model.VaultComponent; +import org.cryptomator.ui.preferences.PreferencesModule; import org.fxmisc.easybind.EasyBind; import javax.inject.Named; @@ -27,7 +28,7 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Consumer; -@Module(includes = {KeychainModule.class, MainWindowModule.class}, subcomponents = {VaultComponent.class}) +@Module(includes = {KeychainModule.class, MainWindowModule.class, PreferencesModule.class}, subcomponents = {VaultComponent.class}) public class UiModule { private static final int NUM_SCHEDULER_THREADS = 4; diff --git a/main/ui/src/main/java/org/cryptomator/ui/mainwindow/MainWindow.java b/main/ui/src/main/java/org/cryptomator/ui/mainwindow/MainWindow.java new file mode 100644 index 000000000..33c534139 --- /dev/null +++ b/main/ui/src/main/java/org/cryptomator/ui/mainwindow/MainWindow.java @@ -0,0 +1,13 @@ +package org.cryptomator.ui.mainwindow; + +import javax.inject.Qualifier; +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Qualifier +@Documented +@Retention(RetentionPolicy.RUNTIME) +public @interface MainWindow { + +} diff --git a/main/ui/src/main/java/org/cryptomator/ui/mainwindow/MainWindowController.java b/main/ui/src/main/java/org/cryptomator/ui/mainwindow/MainWindowController.java index 3a9cbc828..6712f0f34 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/mainwindow/MainWindowController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/mainwindow/MainWindowController.java @@ -1,9 +1,10 @@ package org.cryptomator.ui.mainwindow; -import javafx.application.Application; +import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.scene.layout.HBox; import javafx.stage.Stage; +import org.cryptomator.ui.FxApplication; import org.cryptomator.ui.FxApplicationScoped; import org.cryptomator.ui.FxController; import org.slf4j.Logger; @@ -20,6 +21,7 @@ public class MainWindowController implements FxController { private final CountDownLatch shutdownLatch; private final Stage mainWindow; + private final FxApplication application; @FXML public HBox titleBar; @@ -28,9 +30,10 @@ public class MainWindowController implements FxController { private double yOffset; @Inject - public MainWindowController(@Named("shutdownLatch") CountDownLatch shutdownLatch, @Named("mainWindow") Stage mainWindow) { + public MainWindowController(@Named("shutdownLatch") CountDownLatch shutdownLatch, @MainWindow Stage mainWindow, FxApplication application) { this.shutdownLatch = shutdownLatch; this.mainWindow = mainWindow; + this.application = application; } @FXML @@ -52,4 +55,9 @@ public class MainWindowController implements FxController { LOG.info("closed..."); shutdownLatch.countDown(); } + + @FXML + public void showPreferences() { + application.showPreferencesWindow(); + } } diff --git a/main/ui/src/main/java/org/cryptomator/ui/mainwindow/MainWindowModule.java b/main/ui/src/main/java/org/cryptomator/ui/mainwindow/MainWindowModule.java index c2b2ae5b3..1f6bf0907 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/mainwindow/MainWindowModule.java +++ b/main/ui/src/main/java/org/cryptomator/ui/mainwindow/MainWindowModule.java @@ -7,6 +7,8 @@ import dagger.multibindings.IntoMap; import javafx.beans.property.ObjectProperty; import javafx.beans.property.SimpleObjectProperty; import javafx.collections.ObservableList; +import javafx.stage.Stage; +import javafx.stage.StageStyle; import org.cryptomator.ui.FxApplicationScoped; import org.cryptomator.ui.FxController; import org.cryptomator.ui.FxControllerKey; @@ -33,8 +35,19 @@ public abstract class MainWindowModule { // ------------------ + @Provides + @FxApplicationScoped + @MainWindow + static Stage providePrimaryStage() { + Stage stage = new Stage(); + stage.setMinWidth(652.0); + stage.setMinHeight(440.0); + stage.initStyle(StageStyle.UNDECORATED); + return stage; + } + @Binds - abstract ObservableList provideVaults(VaultList vaultList); + abstract ObservableList bindVaultList(VaultList vaultList); @Provides @FxApplicationScoped diff --git a/main/ui/src/main/java/org/cryptomator/ui/preferences/PreferencesController.java b/main/ui/src/main/java/org/cryptomator/ui/preferences/PreferencesController.java new file mode 100644 index 000000000..1265a3e9f --- /dev/null +++ b/main/ui/src/main/java/org/cryptomator/ui/preferences/PreferencesController.java @@ -0,0 +1,13 @@ +package org.cryptomator.ui.preferences; + +import org.cryptomator.ui.FxController; + +import javax.inject.Inject; + +@PreferencesWindow +public class PreferencesController implements FxController { + + @Inject + PreferencesController() {} + +} diff --git a/main/ui/src/main/java/org/cryptomator/ui/preferences/PreferencesModule.java b/main/ui/src/main/java/org/cryptomator/ui/preferences/PreferencesModule.java new file mode 100644 index 000000000..11896f034 --- /dev/null +++ b/main/ui/src/main/java/org/cryptomator/ui/preferences/PreferencesModule.java @@ -0,0 +1,34 @@ +package org.cryptomator.ui.preferences; + +import dagger.Binds; +import dagger.Module; +import dagger.Provides; +import dagger.multibindings.IntoMap; +import javafx.stage.Modality; +import javafx.stage.Stage; +import org.cryptomator.ui.FxApplicationScoped; +import org.cryptomator.ui.FxController; +import org.cryptomator.ui.FxControllerKey; +import org.cryptomator.ui.mainwindow.MainWindow; + +@Module +public abstract class PreferencesModule { + + @Binds + @IntoMap + @FxControllerKey(PreferencesController.class) + abstract FxController bindPreferencesController(PreferencesController controller); + + @Provides + @FxApplicationScoped + @PreferencesWindow + static Stage providePreferencesStage(@MainWindow Stage mainWindow) { + Stage stage = new Stage(); + stage.setMinWidth(400); + stage.setMinHeight(300); + stage.initModality(Modality.APPLICATION_MODAL); + stage.initOwner(mainWindow); + return stage; + } + +} diff --git a/main/ui/src/main/java/org/cryptomator/ui/preferences/PreferencesWindow.java b/main/ui/src/main/java/org/cryptomator/ui/preferences/PreferencesWindow.java new file mode 100644 index 000000000..a2bc2b81d --- /dev/null +++ b/main/ui/src/main/java/org/cryptomator/ui/preferences/PreferencesWindow.java @@ -0,0 +1,13 @@ +package org.cryptomator.ui.preferences; + +import javax.inject.Qualifier; +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Qualifier +@Documented +@Retention(RetentionPolicy.RUNTIME) +public @interface PreferencesWindow { + +} diff --git a/main/ui/src/main/resources/fxml/main_window.fxml b/main/ui/src/main/resources/fxml/main_window.fxml index 547d7d3d0..a95a3a70b 100644 --- a/main/ui/src/main/resources/fxml/main_window.fxml +++ b/main/ui/src/main/resources/fxml/main_window.fxml @@ -15,7 +15,7 @@ - - + From f7759d254755f1db4d355b1a42d23a5f915f3003 Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Wed, 17 Jul 2019 16:17:23 +0200 Subject: [PATCH 010/264] hooked up all controls in Preferences window --- .../cryptomator/common/settings/Settings.java | 6 +- .../common/settings/SettingsJsonAdapter.java | 14 +++- .../common/settings/WebDavUrlScheme.java | 37 ++++++++++ .../common/settings/SettingsTest.java | 2 +- .../cryptomator/ui/FxApplicationModule.java | 7 -- .../ui/controllers/SettingsController.java | 4 +- .../ui/controls/NumericTextField.java | 20 ++++++ .../cryptomator/ui/model/WebDavVolume.java | 2 +- .../ui/preferences/PreferencesController.java | 68 +++++++++++++++++++ .../src/main/resources/fxml/preferences.fxml | 20 +++--- 10 files changed, 152 insertions(+), 28 deletions(-) create mode 100644 main/commons/src/main/java/org/cryptomator/common/settings/WebDavUrlScheme.java create mode 100644 main/ui/src/main/java/org/cryptomator/ui/controls/NumericTextField.java diff --git a/main/commons/src/main/java/org/cryptomator/common/settings/Settings.java b/main/commons/src/main/java/org/cryptomator/common/settings/Settings.java index 7f57122a3..e345f1779 100644 --- a/main/commons/src/main/java/org/cryptomator/common/settings/Settings.java +++ b/main/commons/src/main/java/org/cryptomator/common/settings/Settings.java @@ -24,7 +24,7 @@ public class Settings { public static final boolean DEFAULT_CHECK_FOR_UDPATES = false; public static final int DEFAULT_PORT = 42427; public static final int DEFAULT_NUM_TRAY_NOTIFICATIONS = 3; - public static final String DEFAULT_GVFS_SCHEME = "dav"; + public static final WebDavUrlScheme DEFAULT_GVFS_SCHEME = WebDavUrlScheme.DAV; public static final boolean DEFAULT_DEBUG_MODE = false; public static final VolumeImpl DEFAULT_PREFERRED_VOLUME_IMPL = System.getProperty("os.name").toLowerCase().contains("windows") ? VolumeImpl.DOKANY : VolumeImpl.FUSE; @@ -33,7 +33,7 @@ public class Settings { private final BooleanProperty checkForUpdates = new SimpleBooleanProperty(DEFAULT_CHECK_FOR_UDPATES); private final IntegerProperty port = new SimpleIntegerProperty(DEFAULT_PORT); private final IntegerProperty numTrayNotifications = new SimpleIntegerProperty(DEFAULT_NUM_TRAY_NOTIFICATIONS); - private final StringProperty preferredGvfsScheme = new SimpleStringProperty(DEFAULT_GVFS_SCHEME); + private final ObjectProperty preferredGvfsScheme = new SimpleObjectProperty<>(DEFAULT_GVFS_SCHEME); private final BooleanProperty debugMode = new SimpleBooleanProperty(DEFAULT_DEBUG_MODE); private final ObjectProperty preferredVolumeImpl = new SimpleObjectProperty<>(DEFAULT_PREFERRED_VOLUME_IMPL); @@ -89,7 +89,7 @@ public class Settings { return numTrayNotifications; } - public StringProperty preferredGvfsScheme() { + public ObjectProperty preferredGvfsScheme() { return preferredGvfsScheme; } diff --git a/main/commons/src/main/java/org/cryptomator/common/settings/SettingsJsonAdapter.java b/main/commons/src/main/java/org/cryptomator/common/settings/SettingsJsonAdapter.java index 6c0bf84ae..609096834 100644 --- a/main/commons/src/main/java/org/cryptomator/common/settings/SettingsJsonAdapter.java +++ b/main/commons/src/main/java/org/cryptomator/common/settings/SettingsJsonAdapter.java @@ -31,7 +31,7 @@ public class SettingsJsonAdapter extends TypeAdapter { out.name("checkForUpdatesEnabled").value(value.checkForUpdates().get()); out.name("port").value(value.port().get()); out.name("numTrayNotifications").value(value.numTrayNotifications().get()); - out.name("preferredGvfsScheme").value(value.preferredGvfsScheme().get()); + out.name("preferredGvfsScheme").value(value.preferredGvfsScheme().get().name()); out.name("debugMode").value(value.debugMode().get()); out.name("preferredVolumeImpl").value(value.preferredVolumeImpl().get().name()); out.endObject(); @@ -69,7 +69,7 @@ public class SettingsJsonAdapter extends TypeAdapter { settings.numTrayNotifications().set(in.nextInt()); break; case "preferredGvfsScheme": - settings.preferredGvfsScheme().set(in.nextString()); + settings.preferredGvfsScheme().set(parseWebDavUrlSchemePrefix(in.nextString())); break; case "debugMode": settings.debugMode().set(in.nextBoolean()); @@ -90,12 +90,20 @@ public class SettingsJsonAdapter extends TypeAdapter { private VolumeImpl parsePreferredVolumeImplName(String nioAdapterName) { try { - return VolumeImpl.valueOf(nioAdapterName); + return VolumeImpl.valueOf(nioAdapterName.toUpperCase()); } catch (IllegalArgumentException e) { return Settings.DEFAULT_PREFERRED_VOLUME_IMPL; } } + private WebDavUrlScheme parseWebDavUrlSchemePrefix(String webDavUrlSchemeName) { + try { + return WebDavUrlScheme.valueOf(webDavUrlSchemeName.toUpperCase()); + } catch (IllegalArgumentException e) { + return Settings.DEFAULT_GVFS_SCHEME; + } + } + private List readVaultSettingsArray(JsonReader in) throws IOException { List result = new ArrayList<>(); in.beginArray(); diff --git a/main/commons/src/main/java/org/cryptomator/common/settings/WebDavUrlScheme.java b/main/commons/src/main/java/org/cryptomator/common/settings/WebDavUrlScheme.java new file mode 100644 index 000000000..b34956c90 --- /dev/null +++ b/main/commons/src/main/java/org/cryptomator/common/settings/WebDavUrlScheme.java @@ -0,0 +1,37 @@ +package org.cryptomator.common.settings; + +import java.util.Arrays; + +public enum WebDavUrlScheme { + DAV("dav", "dav:// (Gnome, Nautilus, ...)"), + WEBDAV("webdav", "webdav:// (KDE, Dolphin, ...)"); + + private final String prefix; + private final String displayName; + + WebDavUrlScheme(String prefix, String displayName) {this.prefix = prefix; + this.displayName = displayName; + } + + public String getPrefix() { + return prefix; + } + + public String getDisplayName() { + return displayName; + } + + /** + * Finds a WebDavUrlScheme by prefix. + * + * @param prefix Prefix of the WebDavUrlScheme + * @return WebDavUrlScheme with the given prefix. + * @throws IllegalArgumentException if not WebDavUrlScheme with the given prefix was found. + */ + public static WebDavUrlScheme forPrefix(String prefix) throws IllegalArgumentException { + return Arrays.stream(values()) // + .filter(impl -> impl.prefix.equals(prefix)) // + .findAny() // + .orElseThrow(IllegalArgumentException::new); + } +} diff --git a/main/commons/src/test/java/org/cryptomator/common/settings/SettingsTest.java b/main/commons/src/test/java/org/cryptomator/common/settings/SettingsTest.java index 6aadb27b3..a0c3f6adb 100644 --- a/main/commons/src/test/java/org/cryptomator/common/settings/SettingsTest.java +++ b/main/commons/src/test/java/org/cryptomator/common/settings/SettingsTest.java @@ -23,7 +23,7 @@ public class SettingsTest { Mockito.verify(changeListener, Mockito.times(0)).accept(settings); // first change (to property): - settings.preferredGvfsScheme().set("asd"); + settings.preferredGvfsScheme().set(WebDavUrlScheme.DAV); Mockito.verify(changeListener, Mockito.times(1)).accept(settings); // second change (to list): diff --git a/main/ui/src/main/java/org/cryptomator/ui/FxApplicationModule.java b/main/ui/src/main/java/org/cryptomator/ui/FxApplicationModule.java index a57e09ec5..9a997ed9a 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/FxApplicationModule.java +++ b/main/ui/src/main/java/org/cryptomator/ui/FxApplicationModule.java @@ -7,18 +7,11 @@ package org.cryptomator.ui; import dagger.Binds; import dagger.Module; -import dagger.Provides; import javafx.application.Application; -import javafx.stage.Stage; -import javafx.stage.StageStyle; - -import javax.inject.Named; @Module(includes = {UiModule.class}) abstract class FxApplicationModule { - - @Binds @FxApplicationScoped abstract Application provideApplication(FxApplication application); diff --git a/main/ui/src/main/java/org/cryptomator/ui/controllers/SettingsController.java b/main/ui/src/main/java/org/cryptomator/ui/controllers/SettingsController.java index b2af10cbe..b84235632 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/controllers/SettingsController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/controllers/SettingsController.java @@ -111,14 +111,14 @@ public class SettingsController implements ViewController { changePortButton.disableProperty().bind(Bindings.createBooleanBinding(this::isPortValid, portField.textProperty()).not()); prefGvfsScheme.getItems().add("dav"); prefGvfsScheme.getItems().add("webdav"); - prefGvfsScheme.setValue(settings.preferredGvfsScheme().get()); + // prefGvfsScheme.setValue(settings.preferredGvfsScheme().get()); prefGvfsSchemeLabel.setVisible(SystemUtils.IS_OS_LINUX); prefGvfsScheme.setVisible(SystemUtils.IS_OS_LINUX); debugModeCheckbox.setSelected(settings.debugMode().get()); settings.checkForUpdates().bind(checkForUpdatesCheckbox.selectedProperty()); - settings.preferredGvfsScheme().bind(prefGvfsScheme.valueProperty()); + // settings.preferredGvfsScheme().bind(prefGvfsScheme.valueProperty()); settings.preferredVolumeImpl().bind(volume.valueProperty()); settings.debugMode().bind(debugModeCheckbox.selectedProperty()); } diff --git a/main/ui/src/main/java/org/cryptomator/ui/controls/NumericTextField.java b/main/ui/src/main/java/org/cryptomator/ui/controls/NumericTextField.java new file mode 100644 index 000000000..d875442c3 --- /dev/null +++ b/main/ui/src/main/java/org/cryptomator/ui/controls/NumericTextField.java @@ -0,0 +1,20 @@ +package org.cryptomator.ui.controls; + +import javafx.scene.control.TextField; +import javafx.scene.control.TextFormatter; + +import java.util.regex.Pattern; + +public class NumericTextField extends TextField { + + private final static Pattern DIGIT_PATTERN = Pattern.compile("\\d*"); + + public NumericTextField() { + this.setTextFormatter(new TextFormatter<>(this::filterNumericTextChange)); + } + + private TextFormatter.Change filterNumericTextChange(TextFormatter.Change change) { + return DIGIT_PATTERN.matcher(change.getText()).matches() ? change : null; + } + +} diff --git a/main/ui/src/main/java/org/cryptomator/ui/model/WebDavVolume.java b/main/ui/src/main/java/org/cryptomator/ui/model/WebDavVolume.java index 118e3a368..c46ff0ffb 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/model/WebDavVolume.java +++ b/main/ui/src/main/java/org/cryptomator/ui/model/WebDavVolume.java @@ -52,7 +52,7 @@ public class WebDavVolume implements Volume { } MountParams mountParams = MountParams.create() // .withWindowsDriveLetter(vaultSettings.winDriveLetter().get()) // - .withPreferredGvfsScheme(settings.preferredGvfsScheme().get())// + .withPreferredGvfsScheme(settings.preferredGvfsScheme().get().getPrefix())// .withWebdavHostname(getLocalhostAliasOrNull()) // .build(); try { diff --git a/main/ui/src/main/java/org/cryptomator/ui/preferences/PreferencesController.java b/main/ui/src/main/java/org/cryptomator/ui/preferences/PreferencesController.java index 63a6fe390..82b6798c1 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/preferences/PreferencesController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/preferences/PreferencesController.java @@ -2,9 +2,14 @@ package org.cryptomator.ui.preferences; import javafx.beans.binding.Bindings; import javafx.beans.binding.BooleanBinding; +import javafx.scene.control.Button; +import javafx.scene.control.CheckBox; import javafx.scene.control.ChoiceBox; +import javafx.scene.control.TextField; +import javafx.util.StringConverter; import org.cryptomator.common.settings.Settings; import org.cryptomator.common.settings.VolumeImpl; +import org.cryptomator.common.settings.WebDavUrlScheme; import org.cryptomator.ui.FxController; import org.cryptomator.ui.model.Volume; @@ -15,7 +20,12 @@ public class PreferencesController implements FxController { private final Settings settings; private final BooleanBinding showWebDavSettings; + public CheckBox checkForUpdatesCheckbox; + public CheckBox debugModeCheckbox; public ChoiceBox volumeTypeChoicBox; + public TextField webDavPortField; + public Button changeWebDavPortButton; + public ChoiceBox webDavUrlSchemeChoiceBox; @Inject PreferencesController(Settings settings) { @@ -24,10 +34,39 @@ public class PreferencesController implements FxController { } public void initialize() { + checkForUpdatesCheckbox.selectedProperty().bindBidirectional(settings.checkForUpdates()); + + debugModeCheckbox.selectedProperty().bindBidirectional(settings.debugMode()); + volumeTypeChoicBox.getItems().addAll(Volume.getCurrentSupportedAdapters()); volumeTypeChoicBox.valueProperty().bindBidirectional(settings.preferredVolumeImpl()); + volumeTypeChoicBox.setConverter(new VolumeImplConverter()); + + webDavPortField.setText(String.valueOf(settings.port().get())); + changeWebDavPortButton.visibleProperty().bind(settings.port().asString().isNotEqualTo(webDavPortField.textProperty())); + changeWebDavPortButton.disableProperty().bind(Bindings.createBooleanBinding(this::validateWebDavPort, webDavPortField.textProperty()).not()); + + webDavUrlSchemeChoiceBox.getItems().addAll(WebDavUrlScheme.values()); + webDavUrlSchemeChoiceBox.valueProperty().bindBidirectional(settings.preferredGvfsScheme()); + webDavUrlSchemeChoiceBox.setConverter(new WebDavUrlSchemeConverter()); } + private boolean validateWebDavPort() { + try { + int port = Integer.parseInt(webDavPortField.getText()); + return port == 0 // choose port automatically + || port >= Settings.MIN_PORT && port <= Settings.MAX_PORT; // port within range + } catch (NumberFormatException e) { + return false; + } + } + + public void doChangeWebDavPort() { + settings.port().set(Integer.parseInt(webDavPortField.getText())); + } + + /* Property Getters */ + public BooleanBinding showWebDavSettingsProperty() { return showWebDavSettings; } @@ -35,4 +74,33 @@ public class PreferencesController implements FxController { public Boolean getShowWebDavSettings() { return showWebDavSettings.get(); } + + /* Helper classes */ + + private static class WebDavUrlSchemeConverter extends StringConverter { + + @Override + public String toString(WebDavUrlScheme scheme) { + return scheme.getDisplayName(); + } + + @Override + public WebDavUrlScheme fromString(String string) { + throw new UnsupportedOperationException(); + } + } + + private static class VolumeImplConverter extends StringConverter { + + @Override + public String toString(VolumeImpl impl) { + return impl.getDisplayName(); + } + + @Override + public VolumeImpl fromString(String string) { + throw new UnsupportedOperationException(); + } + } + } diff --git a/main/ui/src/main/resources/fxml/preferences.fxml b/main/ui/src/main/resources/fxml/preferences.fxml index 567902706..fe3ebff87 100644 --- a/main/ui/src/main/resources/fxml/preferences.fxml +++ b/main/ui/src/main/resources/fxml/preferences.fxml @@ -1,13 +1,13 @@ - - - - - - + + + + + + - From fddae7d0e169ef2a6055117119f1e5b1520daa51 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Mon, 22 Jul 2019 16:53:06 +0200 Subject: [PATCH 018/264] adding back, open and file chooser button. --- .../ChooseExistingVaultController.java | 34 +++++++++++++++++-- .../resources/fxml/addvault_existing.fxml | 6 +++- 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/main/ui/src/main/java/org/cryptomator/ui/addvaultwizard/ChooseExistingVaultController.java b/main/ui/src/main/java/org/cryptomator/ui/addvaultwizard/ChooseExistingVaultController.java index cd431aa5a..5dce1b88c 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/addvaultwizard/ChooseExistingVaultController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/addvaultwizard/ChooseExistingVaultController.java @@ -1,13 +1,43 @@ package org.cryptomator.ui.addvaultwizard; +import javafx.event.ActionEvent; +import javafx.stage.FileChooser; +import javafx.stage.Stage; +import org.cryptomator.ui.common.FXMLLoaderFactory; import org.cryptomator.ui.common.FxController; import javax.inject.Inject; +import java.io.File; +import java.io.IOException; @AddVaultWizardScoped public class ChooseExistingVaultController implements FxController { - @Inject - ChooseExistingVaultController() {} + private final FXMLLoaderFactory fxmlLoaders; + private final Stage window; + @Inject + ChooseExistingVaultController(@AddVaultWizard Stage window, @AddVaultWizard FXMLLoaderFactory fxmlLoaders) { + this.window = window; + this.fxmlLoaders = fxmlLoaders; + } + + public void chooseFile(ActionEvent actionEvent) { + FileChooser fileChooser = new FileChooser(); + fileChooser.setTitle("Open Masterkey File"); + fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("Cryptomator Masterkey", "*.cryptomator")); + final File file = fileChooser.showOpenDialog(window); + if (file != null) { + window.setWidth(100); + } + } + + public void goBack(ActionEvent actionEvent) throws IOException { + fxmlLoaders.setScene("/fxml/addvault_welcome.fxml", window); + + } + + public void confirm(ActionEvent actionEvent) { + window.close(); + } } diff --git a/main/ui/src/main/resources/fxml/addvault_existing.fxml b/main/ui/src/main/resources/fxml/addvault_existing.fxml index 5bee4b22b..16680d695 100644 --- a/main/ui/src/main/resources/fxml/addvault_existing.fxml +++ b/main/ui/src/main/resources/fxml/addvault_existing.fxml @@ -1,6 +1,7 @@ + - + + + From 14de8ffd5955ca4c549bd4921bcbb947451f80d9 Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Tue, 23 Jul 2019 16:51:25 +0200 Subject: [PATCH 023/264] make window resizable (fixes #932) [ci skip] --- .../ui/mainwindow/MainWindowController.java | 15 +++++++++------ .../ui/mainwindow/MainWindowModule.java | 7 +++++-- main/ui/src/main/resources/fxml/main_window.fxml | 13 +++++++++---- main/ui/src/main/resources/fxml/vault_list.fxml | 1 - 4 files changed, 23 insertions(+), 13 deletions(-) diff --git a/main/ui/src/main/java/org/cryptomator/ui/mainwindow/MainWindowController.java b/main/ui/src/main/java/org/cryptomator/ui/mainwindow/MainWindowController.java index 201c652ce..79c094156 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/mainwindow/MainWindowController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/mainwindow/MainWindowController.java @@ -2,9 +2,9 @@ package org.cryptomator.ui.mainwindow; import javafx.fxml.FXML; import javafx.scene.layout.HBox; +import javafx.scene.layout.Region; import javafx.stage.Stage; import org.cryptomator.ui.FxApplication; -import org.cryptomator.ui.FxApplicationScoped; import org.cryptomator.ui.common.FxController; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -21,10 +21,8 @@ public class MainWindowController implements FxController { private final CountDownLatch shutdownLatch; private final Stage window; private final FxApplication application; - - @FXML public HBox titleBar; - + public Region resizer; private double xOffset; private double yOffset; @@ -43,8 +41,13 @@ public class MainWindowController implements FxController { yOffset = event.getSceneY(); }); titleBar.setOnMouseDragged(event -> { - titleBar.getScene().getWindow().setX(event.getScreenX() - xOffset); - titleBar.getScene().getWindow().setY(event.getScreenY() - yOffset); + window.setX(event.getScreenX() - xOffset); + window.setY(event.getScreenY() - yOffset); + }); + resizer.setOnMouseDragged(event -> { + // we know for a fact that window is borderless. i.e. the scene starts at 0/0 of the window. + window.setWidth(event.getSceneX()); + window.setHeight(event.getSceneY()); }); } diff --git a/main/ui/src/main/java/org/cryptomator/ui/mainwindow/MainWindowModule.java b/main/ui/src/main/java/org/cryptomator/ui/mainwindow/MainWindowModule.java index 22c8bc6e7..66c134c3b 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/mainwindow/MainWindowModule.java +++ b/main/ui/src/main/java/org/cryptomator/ui/mainwindow/MainWindowModule.java @@ -29,8 +29,11 @@ public abstract class MainWindowModule { @MainWindowScoped static Stage provideStage() { Stage stage = new Stage(); - stage.setMinWidth(652.0); - stage.setMinHeight(440.0); + // TODO: min/max values chosen arbitrarily. We might wanna take a look at the user's resolution... + stage.setMinWidth(650); + stage.setMinHeight(440); + stage.setMaxWidth(1000); + stage.setMaxHeight(700); stage.initStyle(StageStyle.UNDECORATED); return stage; } diff --git a/main/ui/src/main/resources/fxml/main_window.fxml b/main/ui/src/main/resources/fxml/main_window.fxml index 7b56ed282..6fcf80df3 100644 --- a/main/ui/src/main/resources/fxml/main_window.fxml +++ b/main/ui/src/main/resources/fxml/main_window.fxml @@ -8,6 +8,7 @@ + - - - - + + + + + + + + diff --git a/main/ui/src/main/resources/fxml/vault_list.fxml b/main/ui/src/main/resources/fxml/vault_list.fxml index 84072e878..143760606 100644 --- a/main/ui/src/main/resources/fxml/vault_list.fxml +++ b/main/ui/src/main/resources/fxml/vault_list.fxml @@ -1,7 +1,6 @@ - From 0eb19a287f245164a6fccbebf6bf5d386378c1b1 Mon Sep 17 00:00:00 2001 From: Tobias Hagemann Date: Tue, 23 Jul 2019 17:02:05 +0200 Subject: [PATCH 024/264] updated theme --- main/ui/src/main/resources/css/theme.css | 64 ++++++++++++++----- .../main/resources/fxml/vault_list_cell.fxml | 16 ++--- 2 files changed, 56 insertions(+), 24 deletions(-) diff --git a/main/ui/src/main/resources/css/theme.css b/main/ui/src/main/resources/css/theme.css index 1d1e5b5cc..0c32931be 100644 --- a/main/ui/src/main/resources/css/theme.css +++ b/main/ui/src/main/resources/css/theme.css @@ -9,8 +9,10 @@ PRIMARY_BG: #70A11B; GRAY_LIGHT_BG: #F7F7F7; TEXT_FILL: #222; - CONTROL_BORDER: #CFCFCF; - CONTROL_ARMED: #E1E1E1; + TEXT_FILL_LIGHT: #7E7E7E; + CONTROL_BORDER_NORMAL: #CFCFCF; + CONTROL_BORDER_FOCUSED: #9E9E9E; + CONTROL_BG_ARMED: #E1E1E1; -fx-background-color: GRAY_LIGHT_BG; -fx-text-fill: TEXT_FILL; @@ -43,7 +45,7 @@ } .main-window .title .button:armed .fa-icon { - -fx-fill: CONTROL_ARMED; + -fx-fill: CONTROL_BG_ARMED; } /******************************************************************************* @@ -57,7 +59,7 @@ } .split-pane:horizontal > .split-pane-divider { - -fx-background-color: GRAY_LIGHT_BG, CONTROL_BORDER; + -fx-background-color: GRAY_LIGHT_BG, CONTROL_BORDER_NORMAL; -fx-background-insets: 0, 0 1 0 0; } @@ -72,7 +74,20 @@ } .list-cell:selected { - -fx-background-color: CONTROL_ARMED; + -fx-background-color: CONTROL_BG_ARMED; +} + +.list-cell .lock-icon { + -fx-fill: TEXT_FILL; +} + +.list-cell .label { + -fx-text-fill: TEXT_FILL; +} + +.list-cell .detail-label { + -fx-text-fill: TEXT_FILL_LIGHT; + -fx-font-size: 0.8em; } .onboarding-overlay-arc { @@ -81,7 +96,7 @@ } .toolbar-container { - -fx-border-color: CONTROL_BORDER transparent transparent transparent; + -fx-border-color: CONTROL_BORDER_NORMAL transparent transparent transparent; -fx-border-width: 1px 0 0 0; } @@ -90,10 +105,15 @@ -fx-pref-width: 30px; -fx-background-color: transparent; -fx-background-insets: 0; - -fx-border-color: transparent CONTROL_BORDER transparent transparent; + -fx-background-radius: 0; + -fx-border-color: transparent CONTROL_BORDER_NORMAL transparent transparent; -fx-border-width: 1; } +.toolbar-container .button:armed { + -fx-background-color: CONTROL_BORDER_NORMAL, CONTROL_BG_ARMED; +} + /******************************************************************************* * * * Tooltip * @@ -117,13 +137,17 @@ .text-input { -fx-cursor: text; -fx-text-fill: TEXT_FILL; - -fx-prompt-text-fill: derive(TEXT_FILL, +50%); - -fx-background-color: CONTROL_BORDER, white; + -fx-prompt-text-fill: TEXT_FILL_LIGHT; + -fx-background-color: CONTROL_BORDER_NORMAL, white; -fx-background-insets: 0, 1px; -fx-background-radius: 4px; -fx-padding: 0.3em 0.5em 0.3em 0.5em; } +.text-input:focused { + -fx-background-color: CONTROL_BORDER_FOCUSED, white; +} + /**************************************************************************** * * * Buttons * @@ -134,14 +158,18 @@ -fx-pref-height: 25px; -fx-text-fill: TEXT_FILL; -fx-alignment: CENTER; - -fx-background-color: CONTROL_BORDER, white; + -fx-background-color: CONTROL_BORDER_NORMAL, white; -fx-background-insets: 0, 1px; -fx-background-radius: 4px; -fx-padding: 0.2em 0.4em 0.2em 0.4em; } +.button:focused { + -fx-background-color: CONTROL_BORDER_FOCUSED, white; +} + .button:armed { - -fx-background-color: CONTROL_BORDER, CONTROL_ARMED; + -fx-background-color: CONTROL_BORDER_NORMAL, CONTROL_BG_ARMED; } /******************************************************************************* @@ -156,12 +184,16 @@ } .check-box > .box { - -fx-background-color: CONTROL_BORDER, white; + -fx-background-color: CONTROL_BORDER_NORMAL, white; -fx-background-insets: 0, 1px; -fx-background-radius: 4px; -fx-padding: 0.3em; } +.check-box:focused > .box { + -fx-background-color: CONTROL_BORDER_FOCUSED, white; +} + .check-box > .box > .mark { -fx-background-color: transparent; -fx-padding: 0.4em; @@ -180,14 +212,14 @@ .choice-box { -fx-text-fill: TEXT_FILL; - -fx-background-color: CONTROL_BORDER, white; + -fx-background-color: CONTROL_BORDER_NORMAL, white; -fx-background-insets: 0, 1px; -fx-background-radius: 4px; -fx-padding: 0.3em 0.5em 0.3em 0.5em; } .choice-box:focused { - -fx-background-color: derive(CONTROL_BORDER, -20%), white; + -fx-background-color: CONTROL_BORDER_FOCUSED, white; } .choice-box > .open-button { @@ -202,7 +234,7 @@ } .choice-box .context-menu { - -fx-background-color: CONTROL_BORDER, white; + -fx-background-color: CONTROL_BORDER_NORMAL, white; -fx-background-insets: 0, 1px; -fx-background-radius: 4px; -fx-padding: 0.2em 0 0.2em 0; @@ -217,5 +249,5 @@ } .menu-item:focused { - -fx-background-color: CONTROL_ARMED; + -fx-background-color: CONTROL_BG_ARMED; } diff --git a/main/ui/src/main/resources/fxml/vault_list_cell.fxml b/main/ui/src/main/resources/fxml/vault_list_cell.fxml index af1582206..14e0093f0 100644 --- a/main/ui/src/main/resources/fxml/vault_list_cell.fxml +++ b/main/ui/src/main/resources/fxml/vault_list_cell.fxml @@ -1,25 +1,25 @@ - - - + + + - + - - + + From dd0e548353c6bf5f4a3c613eac02e3471b32c0e7 Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Tue, 23 Jul 2019 17:14:22 +0200 Subject: [PATCH 025/264] =?UTF-8?q?sch=C3=B6n=20is=20German=20for=20beauti?= =?UTF-8?q?ful=20[ci=20skip]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main/ui/src/main/resources/css/theme.css | 12 ++++++++++++ main/ui/src/main/resources/fxml/main_window.fxml | 3 +-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/main/ui/src/main/resources/css/theme.css b/main/ui/src/main/resources/css/theme.css index 0c32931be..7a8d6dd90 100644 --- a/main/ui/src/main/resources/css/theme.css +++ b/main/ui/src/main/resources/css/theme.css @@ -48,6 +48,18 @@ -fx-fill: CONTROL_BG_ARMED; } +.main-window .resizer { + -fx-background-color: linear-gradient(to bottom right, + GRAY_LIGHT_BG 40%, + CONTROL_BORDER_NORMAL 50%, + GRAY_LIGHT_BG 60%, + CONTROL_BORDER_NORMAL 70%, + GRAY_LIGHT_BG 80%, + CONTROL_BORDER_NORMAL 90% + ); + -fx-cursor: nw_resize; +} + /******************************************************************************* * * * SplitPane * diff --git a/main/ui/src/main/resources/fxml/main_window.fxml b/main/ui/src/main/resources/fxml/main_window.fxml index 6fcf80df3..819bccb53 100644 --- a/main/ui/src/main/resources/fxml/main_window.fxml +++ b/main/ui/src/main/resources/fxml/main_window.fxml @@ -44,7 +44,6 @@ - - + From 2a6974055961b315c31d47667dbd9908e735ca23 Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Tue, 23 Jul 2019 18:15:12 +0200 Subject: [PATCH 026/264] sharper gradient stops on hi-res displays [ci skip] --- main/ui/src/main/resources/css/theme.css | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/main/ui/src/main/resources/css/theme.css b/main/ui/src/main/resources/css/theme.css index 7a8d6dd90..c960f5853 100644 --- a/main/ui/src/main/resources/css/theme.css +++ b/main/ui/src/main/resources/css/theme.css @@ -50,12 +50,14 @@ .main-window .resizer { -fx-background-color: linear-gradient(to bottom right, - GRAY_LIGHT_BG 40%, - CONTROL_BORDER_NORMAL 50%, - GRAY_LIGHT_BG 60%, - CONTROL_BORDER_NORMAL 70%, - GRAY_LIGHT_BG 80%, - CONTROL_BORDER_NORMAL 90% + transparent 50%, + CONTROL_BORDER_NORMAL 51%, + CONTROL_BORDER_NORMAL 60%, + transparent 61%, + transparent 70%, + CONTROL_BORDER_NORMAL 71%, + CONTROL_BORDER_NORMAL 80%, + transparent 81% ); -fx-cursor: nw_resize; } From 43c5482542d3966b8c03aae51edd5777a674ba38 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Wed, 24 Jul 2019 11:12:29 +0200 Subject: [PATCH 027/264] move text labeling of addExisting vault wizard to string properties file --- main/ui/src/main/resources/fxml/addvault_existing.fxml | 2 +- main/ui/src/main/resources/i18n/strings.properties | 1 + main/ui/src/main/resources/i18n/strings_en.properties | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/main/ui/src/main/resources/fxml/addvault_existing.fxml b/main/ui/src/main/resources/fxml/addvault_existing.fxml index 31c02eb58..02b7271d4 100644 --- a/main/ui/src/main/resources/fxml/addvault_existing.fxml +++ b/main/ui/src/main/resources/fxml/addvault_existing.fxml @@ -15,7 +15,7 @@ - + diff --git a/main/ui/src/main/resources/fxml/vault_detail.fxml b/main/ui/src/main/resources/fxml/vault_detail.fxml index 123387984..4fa72504b 100644 --- a/main/ui/src/main/resources/fxml/vault_detail.fxml +++ b/main/ui/src/main/resources/fxml/vault_detail.fxml @@ -3,6 +3,7 @@ + - + From a7df100e56aa7ef104140cddfd5e0c4ba405b68d Mon Sep 17 00:00:00 2001 From: infeo Date: Wed, 31 Jul 2019 12:49:21 +0200 Subject: [PATCH 061/264] simplifying bindings --- .../ChooseExistingVaultController.java | 20 +++++++++---------- .../resources/fxml/addvault_existing.fxml | 2 +- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/main/ui/src/main/java/org/cryptomator/ui/addvaultwizard/ChooseExistingVaultController.java b/main/ui/src/main/java/org/cryptomator/ui/addvaultwizard/ChooseExistingVaultController.java index f2fac0c1f..99683d211 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/addvaultwizard/ChooseExistingVaultController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/addvaultwizard/ChooseExistingVaultController.java @@ -1,20 +1,19 @@ package org.cryptomator.ui.addvaultwizard; import dagger.Lazy; -import javafx.beans.property.BooleanProperty; +import javafx.beans.binding.BooleanBinding; import javafx.beans.property.ObjectProperty; -import javafx.beans.property.SimpleBooleanProperty; import javafx.collections.ObservableList; import javafx.fxml.FXML; import javafx.scene.Scene; import javafx.stage.FileChooser; import javafx.stage.Stage; import org.cryptomator.common.settings.VaultSettings; +import org.cryptomator.common.vaults.Vault; +import org.cryptomator.common.vaults.VaultFactory; import org.cryptomator.ui.common.FxController; import org.cryptomator.ui.common.FxmlFile; import org.cryptomator.ui.common.FxmlScene; -import org.cryptomator.common.vaults.Vault; -import org.cryptomator.common.vaults.VaultFactory; import javax.inject.Inject; import java.io.File; @@ -28,7 +27,7 @@ public class ChooseExistingVaultController implements FxController { private final Lazy welcomeScene; private final ObjectProperty vaultPath; private final ObservableList vaults; - private final BooleanProperty isVaultPathNull; + private final BooleanBinding vaultPathIsNull; private final VaultFactory vaultFactory; private final ResourceBundle resourceBundle; @@ -40,8 +39,7 @@ public class ChooseExistingVaultController implements FxController { this.vaults = vaults; this.vaultFactory = vaultFactory; this.resourceBundle = resourceBundle; - this.isVaultPathNull = new SimpleBooleanProperty(); - isVaultPathNull.bind(vaultPath.isNull()); + this.vaultPathIsNull = vaultPath.isNull(); } @FXML @@ -79,12 +77,12 @@ public class ChooseExistingVaultController implements FxController { return vaultPath; } - public boolean getIsVaultPathNull() { - return isVaultPathNull.get(); + public boolean isVaultPathIsNull() { + return vaultPathIsNull.get(); } - public BooleanProperty isVaultPathNullProperty() { - return isVaultPathNull; + public BooleanBinding vaultPathIsNullProperty() { + return vaultPathIsNull; } } diff --git a/main/ui/src/main/resources/fxml/addvault_existing.fxml b/main/ui/src/main/resources/fxml/addvault_existing.fxml index f69046c84..454cff7cd 100644 --- a/main/ui/src/main/resources/fxml/addvault_existing.fxml +++ b/main/ui/src/main/resources/fxml/addvault_existing.fxml @@ -28,7 +28,7 @@ From 09aca188fe64f84fa8cd587142ebecbb786d244a Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Wed, 31 Jul 2019 18:39:13 +0200 Subject: [PATCH 071/264] Implemented manual update check button (references #272) --- .../cryptomator/ui/fxapp/UpdateChecker.java | 21 ++++++++--- .../ui/fxapp/UpdateCheckerModule.java | 8 +---- .../UpdatesPreferencesController.java | 35 ++++++++++++++++--- .../resources/fxml/preferences_updates.fxml | 14 ++++++-- 4 files changed, 59 insertions(+), 19 deletions(-) diff --git a/main/ui/src/main/java/org/cryptomator/ui/fxapp/UpdateChecker.java b/main/ui/src/main/java/org/cryptomator/ui/fxapp/UpdateChecker.java index 53a02130e..8be37b528 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/fxapp/UpdateChecker.java +++ b/main/ui/src/main/java/org/cryptomator/ui/fxapp/UpdateChecker.java @@ -1,8 +1,10 @@ package org.cryptomator.ui.fxapp; +import javafx.beans.binding.BooleanBinding; import javafx.beans.property.ReadOnlyStringProperty; import javafx.beans.property.StringProperty; import javafx.concurrent.ScheduledService; +import javafx.concurrent.Worker; import javafx.concurrent.WorkerStateEvent; import javafx.util.Duration; import org.cryptomator.common.settings.Settings; @@ -36,13 +38,14 @@ public class UpdateChecker { public void startCheckingForUpdates(Duration initialDelay) { updateCheckerService.setDelay(initialDelay); + updateCheckerService.setOnRunning(this::checkStarted); updateCheckerService.setOnSucceeded(this::checkSucceeded); updateCheckerService.setOnFailed(this::checkFailed); updateCheckerService.restart(); } - public ReadOnlyStringProperty latestVersionProperty() { - return latestVersionProperty; + private void checkStarted(WorkerStateEvent event) { + LOG.debug("Checking for updates..."); } private void checkSucceeded(WorkerStateEvent event) { @@ -51,8 +54,8 @@ public class UpdateChecker { LOG.info("Current version: {}, lastest version: {}", currentVersion, latestVersion); // TODO settings.lastVersionCheck = Instant.now() - if (currentVersion != null && semVerComparator.compare(currentVersion, latestVersion) < 0) { - // update is available! + if (currentVersion == null || semVerComparator.compare(currentVersion, latestVersion) < 0) { + // update is available latestVersionProperty.set(latestVersion); } else { latestVersionProperty.set(null); @@ -62,5 +65,15 @@ public class UpdateChecker { private void checkFailed(WorkerStateEvent event) { LOG.warn("Error checking for updates", event.getSource().getException()); } + + /* Observable Properties */ + + public BooleanBinding checkingForUpdatesProperty() { + return updateCheckerService.stateProperty().isEqualTo(Worker.State.RUNNING); + } + + public ReadOnlyStringProperty latestVersionProperty() { + return latestVersionProperty; + } } diff --git a/main/ui/src/main/java/org/cryptomator/ui/fxapp/UpdateCheckerModule.java b/main/ui/src/main/java/org/cryptomator/ui/fxapp/UpdateCheckerModule.java index 0a735865f..8b99dacd1 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/fxapp/UpdateCheckerModule.java +++ b/main/ui/src/main/java/org/cryptomator/ui/fxapp/UpdateCheckerModule.java @@ -10,6 +10,7 @@ import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; import javafx.concurrent.ScheduledService; import javafx.concurrent.Task; +import javafx.concurrent.Worker; import javafx.util.Duration; import org.apache.commons.lang3.SystemUtils; @@ -26,13 +27,6 @@ public abstract class UpdateCheckerModule { private static final URI LATEST_VERSION_URI = URI.create("https://api.cryptomator.org/updates/latestVersion.json"); private static final Duration UPDATE_CHECK_INTERVAL = Duration.hours(3); - @Provides - @Named("checkingForUpdates") - @FxApplicationScoped - static ReadOnlyBooleanProperty provideCheckingForUpdates(ScheduledService updateCheckerService) { - return updateCheckerService.runningProperty(); - } - @Provides @Named("latestVersion") @FxApplicationScoped diff --git a/main/ui/src/main/java/org/cryptomator/ui/preferences/UpdatesPreferencesController.java b/main/ui/src/main/java/org/cryptomator/ui/preferences/UpdatesPreferencesController.java index 4b1b2295b..8c1b2601d 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/preferences/UpdatesPreferencesController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/preferences/UpdatesPreferencesController.java @@ -1,28 +1,36 @@ package org.cryptomator.ui.preferences; import javafx.beans.binding.Bindings; +import javafx.beans.binding.BooleanBinding; import javafx.beans.binding.ObjectBinding; -import javafx.beans.property.ReadOnlyBooleanProperty; +import javafx.beans.property.ReadOnlyStringProperty; import javafx.fxml.FXML; import javafx.scene.control.CheckBox; import javafx.scene.control.ContentDisplay; +import javafx.util.Duration; import org.cryptomator.common.settings.Settings; import org.cryptomator.ui.common.FxController; +import org.cryptomator.ui.fxapp.UpdateChecker; import javax.inject.Inject; -import javax.inject.Named; @PreferencesScoped public class UpdatesPreferencesController implements FxController { private final Settings settings; + private final UpdateChecker updateChecker; private final ObjectBinding checkForUpdatesButtonState; + private final ReadOnlyStringProperty latestVersion; + private final BooleanBinding updateAvailable; public CheckBox checkForUpdatesCheckbox; @Inject - UpdatesPreferencesController(Settings settings, @Named("checkingForUpdates") ReadOnlyBooleanProperty checkingForUpdates) { + UpdatesPreferencesController(Settings settings, UpdateChecker updateChecker) { this.settings = settings; - this.checkForUpdatesButtonState = Bindings.when(checkingForUpdates).then(ContentDisplay.LEFT).otherwise(ContentDisplay.TEXT_ONLY); + this.updateChecker = updateChecker; + this.checkForUpdatesButtonState = Bindings.when(updateChecker.checkingForUpdatesProperty()).then(ContentDisplay.LEFT).otherwise(ContentDisplay.TEXT_ONLY); + this.latestVersion = updateChecker.latestVersionProperty(); + this.updateAvailable = latestVersion.isNotNull(); } public void initialize() { @@ -31,9 +39,10 @@ public class UpdatesPreferencesController implements FxController { @FXML public void checkNow() { + updateChecker.startCheckingForUpdates(Duration.ZERO); } - /* Getter/Setter */ + /* Observable Properties */ public ObjectBinding checkForUpdatesButtonStateProperty() { return checkForUpdatesButtonState; @@ -42,4 +51,20 @@ public class UpdatesPreferencesController implements FxController { public ContentDisplay getCheckForUpdatesButtonState() { return checkForUpdatesButtonState.get(); } + + public ReadOnlyStringProperty latestVersionProperty() { + return latestVersion; + } + + public String getLatestVersion() { + return latestVersion.get(); + } + + public BooleanBinding updateAvailableProperty() { + return updateAvailable; + } + + public boolean isUpdateAvailable() { + return updateAvailable.get(); + } } diff --git a/main/ui/src/main/resources/fxml/preferences_updates.fxml b/main/ui/src/main/resources/fxml/preferences_updates.fxml index a95565d2c..e1050de66 100644 --- a/main/ui/src/main/resources/fxml/preferences_updates.fxml +++ b/main/ui/src/main/resources/fxml/preferences_updates.fxml @@ -1,10 +1,12 @@ - - - + + + + + + + + + + + From 900e556369a733335de663adf606b6628e62cfdf Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Wed, 31 Jul 2019 19:16:14 +0200 Subject: [PATCH 072/264] Show TrayMenu sooner, don't wait for FxApplication to initialize --- .../ui/traymenu/FxApplicationStarter.java | 38 +++++++++---------- .../ui/traymenu/TrayIconController.java | 4 +- .../ui/traymenu/TrayMenuComponent.java | 3 +- .../ui/traymenu/TrayMenuController.java | 10 +++-- 4 files changed, 30 insertions(+), 25 deletions(-) diff --git a/main/ui/src/main/java/org/cryptomator/ui/traymenu/FxApplicationStarter.java b/main/ui/src/main/java/org/cryptomator/ui/traymenu/FxApplicationStarter.java index af3f186c8..cd9308504 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/traymenu/FxApplicationStarter.java +++ b/main/ui/src/main/java/org/cryptomator/ui/traymenu/FxApplicationStarter.java @@ -8,44 +8,44 @@ import org.slf4j.LoggerFactory; import javax.inject.Inject; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionStage; import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; @TrayMenuScoped public class FxApplicationStarter { - + private static final Logger LOG = LoggerFactory.getLogger(FxApplicationStarter.class); - private final CompletableFuture future; private final FxApplicationComponent.Builder fxAppComponent; + private final ExecutorService executor; + private final CompletableFuture future; @Inject - public FxApplicationStarter(FxApplicationComponent.Builder fxAppComponent) { + public FxApplicationStarter(FxApplicationComponent.Builder fxAppComponent, ExecutorService executor) { this.fxAppComponent = fxAppComponent; + this.executor = executor; this.future = new CompletableFuture<>(); } - public synchronized FxApplication get(boolean fromTrayMenu) { + public synchronized CompletionStage get(boolean fromTrayMenu) { if (!future.isDone()) { start(fromTrayMenu); } - try { - return future.get(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new IllegalStateException("Interrupted while waiting for FxApplication startup.", e); - } catch (ExecutionException e) { - throw new IllegalStateException("FxApplication startup failed.", e); - } + return future; } private void start(boolean fromTrayMenu) { - LOG.debug("Starting JavaFX runtime..."); - Platform.startup(() -> { - assert Platform.isFxApplicationThread(); - LOG.debug("JavaFX Runtime started."); - FxApplication app = fxAppComponent.trayMenuSupported(fromTrayMenu).build().application(); - app.start(); - future.complete(app); + executor.submit(() -> { + LOG.info("Starting JavaFX runtime..."); + Platform.startup(() -> { + assert Platform.isFxApplicationThread(); + LOG.info("JavaFX Runtime started."); + FxApplication app = fxAppComponent.trayMenuSupported(fromTrayMenu).build().application(); + app.start(); + future.complete(app); + }); }); } diff --git a/main/ui/src/main/java/org/cryptomator/ui/traymenu/TrayIconController.java b/main/ui/src/main/java/org/cryptomator/ui/traymenu/TrayIconController.java index d3fb34a41..754a8a3c0 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/traymenu/TrayIconController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/traymenu/TrayIconController.java @@ -30,8 +30,6 @@ public class TrayIconController { public void initializeTrayIcon() { settings.theme().addListener(this::themeChanged); - - trayMenuController.initTrayMenu(); try { SystemTray.getSystemTray().add(trayIcon); @@ -39,6 +37,8 @@ public class TrayIconController { } catch (AWTException e) { LOG.error("Error adding tray icon", e); } + + trayMenuController.initTrayMenu(); } private void themeChanged(@SuppressWarnings("unused") Observable observable) { diff --git a/main/ui/src/main/java/org/cryptomator/ui/traymenu/TrayMenuComponent.java b/main/ui/src/main/java/org/cryptomator/ui/traymenu/TrayMenuComponent.java index 1af978b4c..e56936563 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/traymenu/TrayMenuComponent.java +++ b/main/ui/src/main/java/org/cryptomator/ui/traymenu/TrayMenuComponent.java @@ -6,6 +6,7 @@ package org.cryptomator.ui.traymenu; import dagger.Subcomponent; +import org.cryptomator.ui.fxapp.FxApplication; import java.awt.SystemTray; @@ -22,7 +23,7 @@ public interface TrayMenuComponent { trayIconController().initializeTrayIcon(); } else { // show main window directly without any tray support: - fxAppStarter().get(false).showMainWindow(); + fxAppStarter().get(false).thenAccept(FxApplication::showMainWindow); } } diff --git a/main/ui/src/main/java/org/cryptomator/ui/traymenu/TrayMenuController.java b/main/ui/src/main/java/org/cryptomator/ui/traymenu/TrayMenuController.java index 330f1c2a6..64da0c5e5 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/traymenu/TrayMenuController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/traymenu/TrayMenuController.java @@ -4,6 +4,9 @@ import javafx.beans.Observable; import javafx.collections.ObservableList; import org.cryptomator.common.settings.Settings; import org.cryptomator.common.vaults.Vault; +import org.cryptomator.ui.fxapp.FxApplication; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import javax.inject.Inject; import javax.inject.Named; @@ -16,6 +19,8 @@ import java.util.concurrent.CountDownLatch; @TrayMenuScoped class TrayMenuController { + + private static final Logger LOG = LoggerFactory.getLogger(TrayMenuController.class); private final FxApplicationStarter fxApplicationStarter; private final CountDownLatch shutdownLatch; @@ -48,7 +53,6 @@ class TrayMenuController { // show window on start? if (!settings.startHidden().get()) { - // TODO: schedule async to not delay tray menu initialization showMainWindow(null); } } @@ -83,11 +87,11 @@ class TrayMenuController { } private void showMainWindow(ActionEvent actionEvent) { - fxApplicationStarter.get(true).showMainWindow(); + fxApplicationStarter.get(true).thenAccept(FxApplication::showMainWindow); } private void showPreferencesWindow(EventObject actionEvent) { - fxApplicationStarter.get(true).showPreferencesWindow(); + fxApplicationStarter.get(true).thenAccept(FxApplication::showPreferencesWindow); } private void quitApplication(ActionEvent actionEvent) { From be432795748b89e6638bd9f7cae7bc46de9b5d22 Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Wed, 31 Jul 2019 19:17:57 +0200 Subject: [PATCH 073/264] cleanup [ci skip] --- .../ui/traymenu/FxApplicationStarter.java | 2 +- .../cryptomator/ui/traymenu/TrayIconController.java | 2 +- .../cryptomator/ui/traymenu/TrayMenuController.java | 12 ++++-------- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/main/ui/src/main/java/org/cryptomator/ui/traymenu/FxApplicationStarter.java b/main/ui/src/main/java/org/cryptomator/ui/traymenu/FxApplicationStarter.java index cd9308504..de4bbd046 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/traymenu/FxApplicationStarter.java +++ b/main/ui/src/main/java/org/cryptomator/ui/traymenu/FxApplicationStarter.java @@ -38,7 +38,7 @@ public class FxApplicationStarter { private void start(boolean fromTrayMenu) { executor.submit(() -> { - LOG.info("Starting JavaFX runtime..."); + LOG.debug("Starting JavaFX runtime..."); Platform.startup(() -> { assert Platform.isFxApplicationThread(); LOG.info("JavaFX Runtime started."); diff --git a/main/ui/src/main/java/org/cryptomator/ui/traymenu/TrayIconController.java b/main/ui/src/main/java/org/cryptomator/ui/traymenu/TrayIconController.java index 754a8a3c0..1ecb1b388 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/traymenu/TrayIconController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/traymenu/TrayIconController.java @@ -33,7 +33,7 @@ public class TrayIconController { try { SystemTray.getSystemTray().add(trayIcon); - LOG.info("initialized tray icon"); + LOG.debug("initialized tray icon"); } catch (AWTException e) { LOG.error("Error adding tray icon", e); } diff --git a/main/ui/src/main/java/org/cryptomator/ui/traymenu/TrayMenuController.java b/main/ui/src/main/java/org/cryptomator/ui/traymenu/TrayMenuController.java index 64da0c5e5..4fded4161 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/traymenu/TrayMenuController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/traymenu/TrayMenuController.java @@ -5,8 +5,6 @@ import javafx.collections.ObservableList; import org.cryptomator.common.settings.Settings; import org.cryptomator.common.vaults.Vault; import org.cryptomator.ui.fxapp.FxApplication; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import javax.inject.Inject; import javax.inject.Named; @@ -19,8 +17,6 @@ import java.util.concurrent.CountDownLatch; @TrayMenuScoped class TrayMenuController { - - private static final Logger LOG = LoggerFactory.getLogger(TrayMenuController.class); private final FxApplicationStarter fxApplicationStarter; private final CountDownLatch shutdownLatch; @@ -43,14 +39,14 @@ class TrayMenuController { public void initTrayMenu() { vaults.addListener(this::vaultListChanged); - + rebuildMenu(); - + // register preferences shortcut if (Desktop.getDesktop().isSupported(Desktop.Action.APP_PREFERENCES)) { Desktop.getDesktop().setPreferencesHandler(this::showPreferencesWindow); } - + // show window on start? if (!settings.startHidden().get()) { showMainWindow(null); @@ -63,7 +59,7 @@ class TrayMenuController { private void rebuildMenu() { menu.removeAll(); - + MenuItem showMainWindowItem = new MenuItem("TODO show"); showMainWindowItem.addActionListener(this::showMainWindow); menu.add(showMainWindowItem); From e32fbc1d79069e2eb4a85f905a5aea7b5fc8efd6 Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Wed, 31 Jul 2019 19:28:27 +0200 Subject: [PATCH 074/264] Select updates tab when showing preferences window and an update is available --- .../ui/preferences/PreferencesController.java | 29 ++++++++++++++++++- .../src/main/resources/fxml/preferences.fxml | 5 ++-- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/main/ui/src/main/java/org/cryptomator/ui/preferences/PreferencesController.java b/main/ui/src/main/java/org/cryptomator/ui/preferences/PreferencesController.java index f014d9e0a..67d1d8ae4 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/preferences/PreferencesController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/preferences/PreferencesController.java @@ -1,13 +1,40 @@ package org.cryptomator.ui.preferences; +import javafx.beans.binding.BooleanBinding; +import javafx.fxml.FXML; +import javafx.scene.control.Tab; +import javafx.scene.control.TabPane; +import javafx.stage.Stage; +import javafx.stage.WindowEvent; import org.cryptomator.ui.common.FxController; +import org.cryptomator.ui.fxapp.UpdateChecker; import javax.inject.Inject; @PreferencesScoped public class PreferencesController implements FxController { + private final Stage window; + private final BooleanBinding updateAvailable; + public TabPane tabPane; + public Tab generalTab; + public Tab updatesTab; + @Inject - public PreferencesController() {} + public PreferencesController(@PreferencesWindow Stage window, UpdateChecker updateChecker) { + this.window = window; + this.updateAvailable = updateChecker.latestVersionProperty().isNotNull(); + } + + @FXML + public void initialize() { + window.setOnShowing(this::windowWillAppear); + } + + private void windowWillAppear(WindowEvent windowEvent) { + if (updateAvailable.get()) { + tabPane.getSelectionModel().select(updatesTab); + } + } } diff --git a/main/ui/src/main/resources/fxml/preferences.fxml b/main/ui/src/main/resources/fxml/preferences.fxml index b61658561..78dc2ab74 100644 --- a/main/ui/src/main/resources/fxml/preferences.fxml +++ b/main/ui/src/main/resources/fxml/preferences.fxml @@ -4,17 +4,18 @@ - + - + From 70b4b5fb2d61850a13fb913c88b1e1125c181244 Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Thu, 1 Aug 2019 13:14:01 +0200 Subject: [PATCH 075/264] only check for updates automatically if set so in preferences --- .../cryptomator/ui/fxapp/UpdateChecker.java | 13 +++++++- .../ui/fxapp/UpdateCheckerModule.java | 32 ++++++++++++------- .../ui/mainwindow/MainWindowController.java | 3 +- .../UpdatesPreferencesController.java | 2 +- 4 files changed, 35 insertions(+), 15 deletions(-) diff --git a/main/ui/src/main/java/org/cryptomator/ui/fxapp/UpdateChecker.java b/main/ui/src/main/java/org/cryptomator/ui/fxapp/UpdateChecker.java index 8be37b528..778d2b4ed 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/fxapp/UpdateChecker.java +++ b/main/ui/src/main/java/org/cryptomator/ui/fxapp/UpdateChecker.java @@ -20,6 +20,7 @@ import java.util.Optional; public class UpdateChecker { private static final Logger LOG = LoggerFactory.getLogger(UpdateChecker.class); + private static final Duration AUTOCHECK_DELAY = Duration.seconds(5); private final Settings settings; private final Optional applicationVersion; @@ -36,7 +37,17 @@ public class UpdateChecker { this.updateCheckerService = updateCheckerService; } - public void startCheckingForUpdates(Duration initialDelay) { + public void automaticallyCheckForUpdatesIfEnabled() { + if (settings.checkForUpdates().get()) { + startCheckingForUpdates(AUTOCHECK_DELAY); + } + } + + public void checkForUpdatesNow() { + startCheckingForUpdates(Duration.ZERO); + } + + private void startCheckingForUpdates(Duration initialDelay) { updateCheckerService.setDelay(initialDelay); updateCheckerService.setOnRunning(this::checkStarted); updateCheckerService.setOnSucceeded(this::checkSucceeded); diff --git a/main/ui/src/main/java/org/cryptomator/ui/fxapp/UpdateCheckerModule.java b/main/ui/src/main/java/org/cryptomator/ui/fxapp/UpdateCheckerModule.java index 8b99dacd1..73c479579 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/fxapp/UpdateCheckerModule.java +++ b/main/ui/src/main/java/org/cryptomator/ui/fxapp/UpdateCheckerModule.java @@ -2,17 +2,15 @@ package org.cryptomator.ui.fxapp; import dagger.Module; import dagger.Provides; -import javafx.beans.binding.BooleanBinding; -import javafx.beans.property.BooleanProperty; -import javafx.beans.property.ReadOnlyBooleanProperty; -import javafx.beans.property.SimpleBooleanProperty; +import javafx.beans.binding.Bindings; +import javafx.beans.binding.ObjectBinding; import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; import javafx.concurrent.ScheduledService; import javafx.concurrent.Task; -import javafx.concurrent.Worker; import javafx.util.Duration; import org.apache.commons.lang3.SystemUtils; +import org.cryptomator.common.settings.Settings; import javax.inject.Named; import java.net.URI; @@ -36,22 +34,34 @@ public abstract class UpdateCheckerModule { @Provides @FxApplicationScoped - static HttpClient providesHttpClient() { + static HttpClient provideHttpClient() { return HttpClient.newHttpClient(); } @Provides @FxApplicationScoped - static HttpRequest providesCheckForUpdatesRequest(@Named("applicationVersion") Optional applicationVersion) { - String userAgent = String.format("Cryptomator VersionChecker/%s %s %s (%s)", applicationVersion.orElse("SNAPSHOT"), SystemUtils.OS_NAME, SystemUtils.OS_VERSION, SystemUtils.OS_ARCH); + static HttpRequest provideCheckForUpdatesRequest(@Named("applicationVersion") Optional applicationVersion) { + String userAgent = String.format("Cryptomator VersionChecker/%s %s %s (%s)", // + applicationVersion.orElse("SNAPSHOT"), // + SystemUtils.OS_NAME, // + SystemUtils.OS_VERSION, // + SystemUtils.OS_ARCH); // return HttpRequest.newBuilder() // .uri(LATEST_VERSION_URI) // - .header("User-Agent", userAgent).build(); + .header("User-Agent", userAgent) // + .build(); + } + + @Provides + @Named("checkForUpdatesInterval") + @FxApplicationScoped + static ObjectBinding provideCheckForUpdateInterval(Settings settings) { + return Bindings.when(settings.checkForUpdates()).then(UPDATE_CHECK_INTERVAL).otherwise(Duration.INDEFINITE); } @Provides @FxApplicationScoped - static ScheduledService provideCheckForUpdatesService(ExecutorService executor, HttpClient httpClient, HttpRequest checkForUpdatesRequest) { + static ScheduledService provideCheckForUpdatesService(ExecutorService executor, HttpClient httpClient, HttpRequest checkForUpdatesRequest, @Named("checkForUpdatesInterval") ObjectBinding period) { ScheduledService service = new ScheduledService<>() { @Override protected Task createTask() { @@ -59,7 +69,7 @@ public abstract class UpdateCheckerModule { } }; service.setExecutor(executor); - service.setPeriod(UPDATE_CHECK_INTERVAL); + service.periodProperty().bind(period); return service; } diff --git a/main/ui/src/main/java/org/cryptomator/ui/mainwindow/MainWindowController.java b/main/ui/src/main/java/org/cryptomator/ui/mainwindow/MainWindowController.java index 50839a110..3cbcfff32 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/mainwindow/MainWindowController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/mainwindow/MainWindowController.java @@ -20,7 +20,6 @@ import java.util.concurrent.CountDownLatch; public class MainWindowController implements FxController { private static final Logger LOG = LoggerFactory.getLogger(MainWindowController.class); - private static final Duration CHECK_FOR_UPDATES_DELAY = Duration.seconds(5); private final Stage window; private final FxApplication application; @@ -57,7 +56,7 @@ public class MainWindowController implements FxController { window.setWidth(event.getSceneX()); window.setHeight(event.getSceneY()); }); - updateChecker.startCheckingForUpdates(CHECK_FOR_UPDATES_DELAY); + updateChecker.automaticallyCheckForUpdatesIfEnabled(); } @FXML diff --git a/main/ui/src/main/java/org/cryptomator/ui/preferences/UpdatesPreferencesController.java b/main/ui/src/main/java/org/cryptomator/ui/preferences/UpdatesPreferencesController.java index 8c1b2601d..aa21eebf3 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/preferences/UpdatesPreferencesController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/preferences/UpdatesPreferencesController.java @@ -39,7 +39,7 @@ public class UpdatesPreferencesController implements FxController { @FXML public void checkNow() { - updateChecker.startCheckingForUpdates(Duration.ZERO); + updateChecker.checkForUpdatesNow(); } /* Observable Properties */ From d51debf736b980f53575fd91fe6d64fb48c9061a Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Thu, 1 Aug 2019 13:24:47 +0200 Subject: [PATCH 076/264] fixed exception when scheduling the next regular update check while auto check is disabled [ci skip] --- .../java/org/cryptomator/ui/fxapp/UpdateCheckerModule.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/main/ui/src/main/java/org/cryptomator/ui/fxapp/UpdateCheckerModule.java b/main/ui/src/main/java/org/cryptomator/ui/fxapp/UpdateCheckerModule.java index 73c479579..7784bd89e 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/fxapp/UpdateCheckerModule.java +++ b/main/ui/src/main/java/org/cryptomator/ui/fxapp/UpdateCheckerModule.java @@ -24,6 +24,7 @@ public abstract class UpdateCheckerModule { private static final URI LATEST_VERSION_URI = URI.create("https://api.cryptomator.org/updates/latestVersion.json"); private static final Duration UPDATE_CHECK_INTERVAL = Duration.hours(3); + private static final Duration DISABLED_UPDATE_CHECK_INTERVAL = Duration.hours(100000); // Duration.INDEFINITE leads to overflows... @Provides @Named("latestVersion") @@ -56,7 +57,7 @@ public abstract class UpdateCheckerModule { @Named("checkForUpdatesInterval") @FxApplicationScoped static ObjectBinding provideCheckForUpdateInterval(Settings settings) { - return Bindings.when(settings.checkForUpdates()).then(UPDATE_CHECK_INTERVAL).otherwise(Duration.INDEFINITE); + return Bindings.when(settings.checkForUpdates()).then(UPDATE_CHECK_INTERVAL).otherwise(DISABLED_UPDATE_CHECK_INTERVAL); } @Provides From 2024c95be5decfbea0419309a04649af60bdb6aa Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Thu, 1 Aug 2019 16:02:09 +0200 Subject: [PATCH 077/264] add actionlistener to tray icon --- .../ui/traymenu/TrayIconController.java | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/main/ui/src/main/java/org/cryptomator/ui/traymenu/TrayIconController.java b/main/ui/src/main/java/org/cryptomator/ui/traymenu/TrayIconController.java index 1ecb1b388..905d6235b 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/traymenu/TrayIconController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/traymenu/TrayIconController.java @@ -1,6 +1,7 @@ package org.cryptomator.ui.traymenu; import javafx.beans.Observable; +import org.apache.commons.lang3.SystemUtils; import org.cryptomator.common.settings.Settings; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -9,10 +10,13 @@ import javax.inject.Inject; import java.awt.AWTException; import java.awt.SystemTray; import java.awt.TrayIcon; +import java.awt.event.ActionEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; @TrayMenuScoped public class TrayIconController { - + private static final Logger LOG = LoggerFactory.getLogger(TrayIconController.class); private final Settings settings; @@ -27,17 +31,22 @@ public class TrayIconController { this.imageFactory = imageFactory; this.trayIcon = new TrayIcon(imageFactory.loadImage(), "Cryptomator", trayMenuController.getMenu()); } - + public void initializeTrayIcon() { settings.theme().addListener(this::themeChanged); + if (SystemUtils.IS_OS_WINDOWS) { + // TODO: test on windows: is this a double click? + trayIcon.addActionListener(trayMenuController::showMainWindow); + } + try { SystemTray.getSystemTray().add(trayIcon); LOG.debug("initialized tray icon"); } catch (AWTException e) { LOG.error("Error adding tray icon", e); } - + trayMenuController.initTrayMenu(); } @@ -45,5 +54,4 @@ public class TrayIconController { trayIcon.setImage(imageFactory.loadImage()); } - } From b86d4b5a374d238a304e5e0af4d6e4ec2d2effd2 Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Thu, 1 Aug 2019 16:02:48 +0200 Subject: [PATCH 078/264] rebuild tray menu when vault state changes --- .../ui/traymenu/TrayMenuController.java | 38 +++++++++++++++---- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/main/ui/src/main/java/org/cryptomator/ui/traymenu/TrayMenuController.java b/main/ui/src/main/java/org/cryptomator/ui/traymenu/TrayMenuController.java index 4fded4161..b5ef4c9cf 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/traymenu/TrayMenuController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/traymenu/TrayMenuController.java @@ -9,6 +9,7 @@ import org.cryptomator.ui.fxapp.FxApplication; import javax.inject.Inject; import javax.inject.Named; import java.awt.Desktop; +import java.awt.Menu; import java.awt.MenuItem; import java.awt.PopupMenu; import java.awt.event.ActionEvent; @@ -53,7 +54,7 @@ class TrayMenuController { } } - private void vaultListChanged(Observable observable) { + private void vaultListChanged(@SuppressWarnings("unused") Observable observable) { rebuildMenu(); } @@ -70,27 +71,48 @@ class TrayMenuController { menu.addSeparator(); for (Vault v : vaults) { - // TODO what do we want to do with these? lock/unlock? reveal? submenu? - MenuItem vaultItem = new MenuItem(v.getDisplayableName()); - menu.add(vaultItem); + MenuItem submenu = buildSubmenu(v); + menu.add(submenu); } menu.addSeparator(); MenuItem quitApplicationItem = new MenuItem("TODO quit"); quitApplicationItem.addActionListener(this::quitApplication); menu.add(quitApplicationItem); - } - private void showMainWindow(ActionEvent actionEvent) { + private Menu buildSubmenu(Vault vault) { + Menu submenu = new Menu(vault.getDisplayableName()); + vault.stateProperty().addListener(observable -> rebuildSubmenu(submenu, vault)); + rebuildSubmenu(submenu, vault); + return submenu; + } + + private void rebuildSubmenu(Menu submenu, Vault vault) { + submenu.removeAll(); + + // TODO add action listeners + if (vault.isLocked()) { + MenuItem unlockItem = new MenuItem("TODO unlock"); + submenu.add(unlockItem); + } else if (vault.isUnlocked()) { + MenuItem lockItem = new MenuItem("TODO lock"); + submenu.add(lockItem); + + MenuItem revealItem = new MenuItem("TODO reveal"); + submenu.add(revealItem); + } + } + + void showMainWindow(@SuppressWarnings("unused") ActionEvent actionEvent) { fxApplicationStarter.get(true).thenAccept(FxApplication::showMainWindow); } - private void showPreferencesWindow(EventObject actionEvent) { + void showPreferencesWindow(@SuppressWarnings("unused") EventObject actionEvent) { fxApplicationStarter.get(true).thenAccept(FxApplication::showPreferencesWindow); } - private void quitApplication(ActionEvent actionEvent) { + void quitApplication(@SuppressWarnings("unused") ActionEvent actionEvent) { shutdownLatch.countDown(); } } From e23dc728567db46d7426ec996030b925c119ab00 Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Thu, 1 Aug 2019 16:14:38 +0200 Subject: [PATCH 079/264] Can now unlock directly from menu bar --- .../cryptomator/ui/fxapp/FxApplication.java | 13 ++++++- .../ui/mainwindow/VaultDetailController.java | 35 ++++++++++--------- .../ui/traymenu/TrayMenuController.java | 11 ++++++ 3 files changed, 42 insertions(+), 17 deletions(-) diff --git a/main/ui/src/main/java/org/cryptomator/ui/fxapp/FxApplication.java b/main/ui/src/main/java/org/cryptomator/ui/fxapp/FxApplication.java index c75aeea8d..dd1fb4152 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/fxapp/FxApplication.java +++ b/main/ui/src/main/java/org/cryptomator/ui/fxapp/FxApplication.java @@ -7,10 +7,12 @@ import javafx.beans.value.ObservableValue; import javafx.stage.Stage; import org.cryptomator.common.settings.Settings; import org.cryptomator.common.settings.UiTheme; +import org.cryptomator.common.vaults.Vault; import org.cryptomator.jni.MacApplicationUiAppearance; import org.cryptomator.jni.MacFunctions; import org.cryptomator.ui.mainwindow.MainWindowComponent; import org.cryptomator.ui.preferences.PreferencesComponent; +import org.cryptomator.ui.unlock.UnlockComponent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -27,13 +29,15 @@ public class FxApplication extends Application { private final Settings settings; private final Lazy mainWindow; private final Lazy preferencesWindow; + private final UnlockComponent.Builder unlockWindowBuilder; private final Optional macFunctions; @Inject - FxApplication(Settings settings, Lazy mainWindow, Lazy preferencesWindow, Optional macFunctions) { + FxApplication(Settings settings, Lazy mainWindow, Lazy preferencesWindow, UnlockComponent.Builder unlockWindowBuilder, Optional macFunctions) { this.settings = settings; this.mainWindow = mainWindow; this.preferencesWindow = preferencesWindow; + this.unlockWindowBuilder = unlockWindowBuilder; this.macFunctions = macFunctions; } @@ -64,6 +68,13 @@ public class FxApplication extends Application { }); } + public void showUnlockWindow(Vault vault) { + Platform.runLater(() -> { + unlockWindowBuilder.vault(vault).build().showUnlockWindow(); + LOG.debug("Showing UnlockWindow for {}", vault.getDisplayableName()); + }); + } + private void themeChanged(@SuppressWarnings("unused") ObservableValue observable, @SuppressWarnings("unused") UiTheme oldValue, UiTheme newValue) { loadSelectedStyleSheet(newValue); } diff --git a/main/ui/src/main/java/org/cryptomator/ui/mainwindow/VaultDetailController.java b/main/ui/src/main/java/org/cryptomator/ui/mainwindow/VaultDetailController.java index 3cf8bee64..d16aa4b4c 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/mainwindow/VaultDetailController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/mainwindow/VaultDetailController.java @@ -3,10 +3,10 @@ package org.cryptomator.ui.mainwindow; import javafx.beans.property.ObjectProperty; import javafx.beans.property.ReadOnlyObjectProperty; import javafx.fxml.FXML; +import org.cryptomator.common.vaults.Vault; import org.cryptomator.ui.common.FxController; import org.cryptomator.ui.common.Tasks; -import org.cryptomator.common.vaults.Vault; -import org.cryptomator.ui.unlock.UnlockComponent; +import org.cryptomator.ui.fxapp.FxApplication; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -15,31 +15,23 @@ import java.util.concurrent.ExecutorService; @MainWindowScoped public class VaultDetailController implements FxController { - + private static final Logger LOG = LoggerFactory.getLogger(VaultDetailController.class); - + private final ReadOnlyObjectProperty vault; private final ExecutorService executor; - private final UnlockComponent.Builder unlockWindow; + private final FxApplication application; @Inject - VaultDetailController(ObjectProperty vault, ExecutorService executor, UnlockComponent.Builder unlockWindow) { + VaultDetailController(ObjectProperty vault, ExecutorService executor, FxApplication application) { this.vault = vault; this.executor = executor; - this.unlockWindow = unlockWindow; - } - - public ReadOnlyObjectProperty vaultProperty() { - return vault; - } - - public Vault getVault() { - return vault.get(); + this.application = application; } @FXML public void unlock() { - unlockWindow.vault(vault.get()).build().showUnlockWindow(); + application.showUnlockWindow(vault.get()); } @FXML @@ -55,4 +47,15 @@ public class VaultDetailController implements FxController { // TODO }).runOnce(executor); } + + /* Observable Properties */ + + public ReadOnlyObjectProperty vaultProperty() { + return vault; + } + + public Vault getVault() { + return vault.get(); + } + } diff --git a/main/ui/src/main/java/org/cryptomator/ui/traymenu/TrayMenuController.java b/main/ui/src/main/java/org/cryptomator/ui/traymenu/TrayMenuController.java index b5ef4c9cf..1c7aaa7d9 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/traymenu/TrayMenuController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/traymenu/TrayMenuController.java @@ -13,8 +13,10 @@ import java.awt.Menu; import java.awt.MenuItem; import java.awt.PopupMenu; import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; import java.util.EventObject; import java.util.concurrent.CountDownLatch; +import java.util.function.Consumer; @TrayMenuScoped class TrayMenuController { @@ -94,6 +96,7 @@ class TrayMenuController { // TODO add action listeners if (vault.isLocked()) { MenuItem unlockItem = new MenuItem("TODO unlock"); + unlockItem.addActionListener(createActionListenerForVault(vault, this::unlockVault)); submenu.add(unlockItem); } else if (vault.isUnlocked()) { MenuItem lockItem = new MenuItem("TODO lock"); @@ -104,6 +107,14 @@ class TrayMenuController { } } + private ActionListener createActionListenerForVault(Vault vault, Consumer consumer) { + return actionEvent -> consumer.accept(vault); + } + + private void unlockVault(Vault vault) { + fxApplicationStarter.get(true).thenAccept(app -> app.showUnlockWindow(vault)); + } + void showMainWindow(@SuppressWarnings("unused") ActionEvent actionEvent) { fxApplicationStarter.get(true).thenAccept(FxApplication::showMainWindow); } From 67610b935eb011c11607935468ffd293acdc8441 Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Tue, 6 Aug 2019 11:09:00 +0200 Subject: [PATCH 080/264] Added vault settings window (references #931) --- .../org/cryptomator/ui/common/FxmlFile.java | 3 +- .../ui/mainwindow/MainWindowModule.java | 3 +- .../ui/mainwindow/VaultDetailController.java | 10 ++- .../GeneralVaultOptionsController.java | 13 ++++ .../vaultoptions/MountOptionsController.java | 13 ++++ .../vaultoptions/VaultOptionsComponent.java | 43 +++++++++++ .../vaultoptions/VaultOptionsController.java | 13 ++++ .../ui/vaultoptions/VaultOptionsModule.java | 72 +++++++++++++++++++ .../ui/vaultoptions/VaultOptionsScoped.java | 13 ++++ .../ui/vaultoptions/VaultOptionsWindow.java | 14 ++++ .../src/main/resources/fxml/vault_detail.fxml | 1 + .../main/resources/fxml/vault_options.fxml | 24 +++++++ .../resources/fxml/vault_options_general.fxml | 16 +++++ .../resources/fxml/vault_options_mount.fxml | 16 +++++ 14 files changed, 251 insertions(+), 3 deletions(-) create mode 100644 main/ui/src/main/java/org/cryptomator/ui/vaultoptions/GeneralVaultOptionsController.java create mode 100644 main/ui/src/main/java/org/cryptomator/ui/vaultoptions/MountOptionsController.java create mode 100644 main/ui/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsComponent.java create mode 100644 main/ui/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsController.java create mode 100644 main/ui/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsModule.java create mode 100644 main/ui/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsScoped.java create mode 100644 main/ui/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsWindow.java create mode 100644 main/ui/src/main/resources/fxml/vault_options.fxml create mode 100644 main/ui/src/main/resources/fxml/vault_options_general.fxml create mode 100644 main/ui/src/main/resources/fxml/vault_options_mount.fxml diff --git a/main/ui/src/main/java/org/cryptomator/ui/common/FxmlFile.java b/main/ui/src/main/java/org/cryptomator/ui/common/FxmlFile.java index 1ec24dcaf..0f30aeab8 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/common/FxmlFile.java +++ b/main/ui/src/main/java/org/cryptomator/ui/common/FxmlFile.java @@ -9,7 +9,8 @@ public enum FxmlFile { ADDVAULT_NEW_PASSWORD("/fxml/addvault_new_password.fxml"), // PREFERENCES("/fxml/preferences.fxml"), // UNLOCK("/fxml/unlock2.fxml"), // TODO rename - UNLOCK_SUCCESS("/fxml/unlock_success.fxml"); + UNLOCK_SUCCESS("/fxml/unlock_success.fxml"), + VAULT_OPTIONS("/fxml/vault_options.fxml"); private final String filename; diff --git a/main/ui/src/main/java/org/cryptomator/ui/mainwindow/MainWindowModule.java b/main/ui/src/main/java/org/cryptomator/ui/mainwindow/MainWindowModule.java index 43c979d8c..2660662ea 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/mainwindow/MainWindowModule.java +++ b/main/ui/src/main/java/org/cryptomator/ui/mainwindow/MainWindowModule.java @@ -13,12 +13,13 @@ import org.cryptomator.ui.common.FxController; import org.cryptomator.ui.common.FxControllerKey; import org.cryptomator.ui.common.FxmlFile; import org.cryptomator.ui.common.FxmlScene; +import org.cryptomator.ui.vaultoptions.VaultOptionsComponent; import javax.inject.Provider; import java.util.Map; import java.util.ResourceBundle; -@Module(subcomponents = {AddVaultWizardComponent.class}) +@Module(subcomponents = {AddVaultWizardComponent.class, VaultOptionsComponent.class}) abstract class MainWindowModule { @Provides diff --git a/main/ui/src/main/java/org/cryptomator/ui/mainwindow/VaultDetailController.java b/main/ui/src/main/java/org/cryptomator/ui/mainwindow/VaultDetailController.java index d16aa4b4c..eec1a2f79 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/mainwindow/VaultDetailController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/mainwindow/VaultDetailController.java @@ -7,6 +7,7 @@ import org.cryptomator.common.vaults.Vault; import org.cryptomator.ui.common.FxController; import org.cryptomator.ui.common.Tasks; import org.cryptomator.ui.fxapp.FxApplication; +import org.cryptomator.ui.vaultoptions.VaultOptionsComponent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -21,12 +22,14 @@ public class VaultDetailController implements FxController { private final ReadOnlyObjectProperty vault; private final ExecutorService executor; private final FxApplication application; + private final VaultOptionsComponent.Builder vaultOptionsWindow; @Inject - VaultDetailController(ObjectProperty vault, ExecutorService executor, FxApplication application) { + VaultDetailController(ObjectProperty vault, ExecutorService executor, FxApplication application, VaultOptionsComponent.Builder vaultOptionsWindow) { this.vault = vault; this.executor = executor; this.application = application; + this.vaultOptionsWindow = vaultOptionsWindow; } @FXML @@ -47,6 +50,11 @@ public class VaultDetailController implements FxController { // TODO }).runOnce(executor); } + + @FXML + public void showVaultOptions() { + vaultOptionsWindow.vault(vault.get()).build().showVaultOptionsWindow(); + } /* Observable Properties */ diff --git a/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/GeneralVaultOptionsController.java b/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/GeneralVaultOptionsController.java new file mode 100644 index 000000000..7a7f5e59d --- /dev/null +++ b/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/GeneralVaultOptionsController.java @@ -0,0 +1,13 @@ +package org.cryptomator.ui.vaultoptions; + +import org.cryptomator.ui.common.FxController; + +import javax.inject.Inject; + +@VaultOptionsScoped +public class GeneralVaultOptionsController implements FxController { + + @Inject + GeneralVaultOptionsController(){} + +} diff --git a/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/MountOptionsController.java b/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/MountOptionsController.java new file mode 100644 index 000000000..e5117b8cd --- /dev/null +++ b/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/MountOptionsController.java @@ -0,0 +1,13 @@ +package org.cryptomator.ui.vaultoptions; + +import org.cryptomator.ui.common.FxController; + +import javax.inject.Inject; + +@VaultOptionsScoped +public class MountOptionsController implements FxController { + + @Inject + MountOptionsController(){} + +} diff --git a/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsComponent.java b/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsComponent.java new file mode 100644 index 000000000..ce1dcaa2e --- /dev/null +++ b/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsComponent.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * 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.vaultoptions; + +import dagger.BindsInstance; +import dagger.Lazy; +import dagger.Subcomponent; +import javafx.scene.Scene; +import javafx.stage.Stage; +import org.cryptomator.common.vaults.Vault; +import org.cryptomator.ui.common.FxmlFile; +import org.cryptomator.ui.common.FxmlScene; + +@VaultOptionsScoped +@Subcomponent(modules = {VaultOptionsModule.class}) +public interface VaultOptionsComponent { + + @VaultOptionsWindow + Stage window(); + + @FxmlScene(FxmlFile.VAULT_OPTIONS) + Lazy scene(); + + default void showVaultOptionsWindow() { + Stage stage = window(); + stage.setScene(scene().get()); + stage.show(); + stage.requestFocus(); + } + + @Subcomponent.Builder + interface Builder { + + @BindsInstance + VaultOptionsComponent.Builder vault(@VaultOptionsWindow Vault vault); + + VaultOptionsComponent build(); + } + +} diff --git a/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsController.java b/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsController.java new file mode 100644 index 000000000..9b525c2a3 --- /dev/null +++ b/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsController.java @@ -0,0 +1,13 @@ +package org.cryptomator.ui.vaultoptions; + +import org.cryptomator.ui.common.FxController; + +import javax.inject.Inject; + +@VaultOptionsScoped +public class VaultOptionsController implements FxController { + + @Inject + VaultOptionsController(){} + +} diff --git a/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsModule.java b/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsModule.java new file mode 100644 index 000000000..1cc869437 --- /dev/null +++ b/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsModule.java @@ -0,0 +1,72 @@ +package org.cryptomator.ui.vaultoptions; + +import dagger.Binds; +import dagger.Module; +import dagger.Provides; +import dagger.multibindings.IntoMap; +import javafx.scene.Scene; +import javafx.stage.Modality; +import javafx.stage.Stage; +import javafx.stage.StageStyle; +import org.cryptomator.common.vaults.Vault; +import org.cryptomator.ui.common.FXMLLoaderFactory; +import org.cryptomator.ui.common.FxController; +import org.cryptomator.ui.common.FxControllerKey; +import org.cryptomator.ui.common.FxmlFile; +import org.cryptomator.ui.common.FxmlScene; +import org.cryptomator.ui.mainwindow.MainWindow; + +import javax.inject.Provider; +import java.util.Map; +import java.util.ResourceBundle; + +@Module +abstract class VaultOptionsModule { + + @Provides + @VaultOptionsWindow + @VaultOptionsScoped + static FXMLLoaderFactory provideFxmlLoaderFactory(Map, Provider> factories, ResourceBundle resourceBundle) { + return new FXMLLoaderFactory(factories, resourceBundle); + } + + @Provides + @VaultOptionsWindow + @VaultOptionsScoped + static Stage provideStage(@MainWindow Stage owner, @VaultOptionsWindow Vault vault, ResourceBundle resourceBundle) { + Stage stage = new Stage(); + stage.setTitle(vault.getDisplayableName()); + // stage.setTitle(resourceBundle.getString("vaultOptions.title")); + stage.setMinWidth(400); + stage.setMinHeight(300); + stage.initStyle(StageStyle.DECORATED); + stage.initModality(Modality.WINDOW_MODAL); + stage.initOwner(owner); + return stage; + } + + @Provides + @FxmlScene(FxmlFile.VAULT_OPTIONS) + @VaultOptionsScoped + static Scene provideVaultOptionsScene(@VaultOptionsWindow FXMLLoaderFactory fxmlLoaders) { + return fxmlLoaders.createScene("/fxml/vault_options.fxml"); + } + + // ------------------ + + @Binds + @IntoMap + @FxControllerKey(VaultOptionsController.class) + abstract FxController bindVaultOptionsController(VaultOptionsController controller); + + @Binds + @IntoMap + @FxControllerKey(GeneralVaultOptionsController.class) + abstract FxController bindGeneralVaultOptionsController(GeneralVaultOptionsController controller); + + @Binds + @IntoMap + @FxControllerKey(MountOptionsController.class) + abstract FxController bindMountOptionsController(MountOptionsController controller); + +} diff --git a/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsScoped.java b/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsScoped.java new file mode 100644 index 000000000..cd8568171 --- /dev/null +++ b/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsScoped.java @@ -0,0 +1,13 @@ +package org.cryptomator.ui.vaultoptions; + +import javax.inject.Scope; +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Scope +@Documented +@Retention(RetentionPolicy.RUNTIME) +@interface VaultOptionsScoped { + +} diff --git a/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsWindow.java b/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsWindow.java new file mode 100644 index 000000000..db3e25bd2 --- /dev/null +++ b/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsWindow.java @@ -0,0 +1,14 @@ +package org.cryptomator.ui.vaultoptions; + +import javax.inject.Qualifier; +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; + +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +@Qualifier +@Documented +@Retention(RUNTIME) +public @interface VaultOptionsWindow { + +} diff --git a/main/ui/src/main/resources/fxml/vault_detail.fxml b/main/ui/src/main/resources/fxml/vault_detail.fxml index 4fa72504b..66bcd0824 100644 --- a/main/ui/src/main/resources/fxml/vault_detail.fxml +++ b/main/ui/src/main/resources/fxml/vault_detail.fxml @@ -16,5 +16,6 @@ + + + From d77403c4035acba4493357141d322cf10b4db8ea Mon Sep 17 00:00:00 2001 From: Tobias Hagemann Date: Tue, 6 Aug 2019 16:15:43 +0200 Subject: [PATCH 085/264] updated tab pane styling [ci skip] --- main/ui/src/main/resources/css/dark_theme.css | 23 +++++++++++------- .../ui/src/main/resources/css/light_theme.css | 24 ++++++++++++------- 2 files changed, 29 insertions(+), 18 deletions(-) diff --git a/main/ui/src/main/resources/css/dark_theme.css b/main/ui/src/main/resources/css/dark_theme.css index 3ba21ba99..24d77b829 100644 --- a/main/ui/src/main/resources/css/dark_theme.css +++ b/main/ui/src/main/resources/css/dark_theme.css @@ -97,26 +97,32 @@ ******************************************************************************/ .tab-pane { - -fx-tab-min-height: 24; + -fx-tab-min-height: 2em; } + .tab-pane > .tab-header-area { -fx-padding: 6px 12px 0 12px; -fx-background-color: CONTROL_BORDER_FOCUSED, MAIN_BG; - -fx-background-insets: 0, 0 0 1 0; + -fx-background-insets: 0, 0 0 1px 0; } + .tab-pane > .tab-header-area > .headers-region > .tab { - -fx-text-fill: TEXT_FILL; - -fx-alignment: CENTER; - -fx-background-color: CONTROL_BORDER_NORMAL, CONTROL_BORDER_FOCUSED, MAIN_BG; - -fx-background-insets: 0, 1px 1px 0 1px, 1px; + -fx-background-color: CONTROL_BORDER_NORMAL, MAIN_BG; + -fx-background-insets: 0 0 1px 0, 1px; -fx-background-radius: 4px 4px 0 0; -fx-padding: 0.2em 0.4em 0.2em 0.4em; } + .tab-pane > .tab-header-area > .headers-region > .tab:selected { -fx-background-color: CONTROL_BORDER_FOCUSED, MAIN_BG; -fx-background-insets: 0, 1px 1px 0 1px; } +.tab-pane > .tab-header-area > .headers-region > .tab > .tab-container > .tab-label { + -fx-text-fill: TEXT_FILL; + -fx-alignment: CENTER; +} + /******************************************************************************* * * * SplitPane * @@ -139,7 +145,7 @@ ******************************************************************************/ .list-view { - -fx-background-color: CONTROL_BG_NORMAL; + -fx-background-color: CONTROL_BG_NORMAL; } .list-cell:selected { @@ -165,7 +171,6 @@ -fx-border-width: 0 0 3px 0; } - .onboarding-overlay-arc { -fx-stroke: TEXT_FILL; -fx-fill: transparent; @@ -183,7 +188,7 @@ -fx-background-insets: 0; -fx-background-radius: 0; -fx-border-color: transparent CONTROL_BORDER_NORMAL transparent transparent; - -fx-border-width: 1; + -fx-border-width: 1; } .toolbar-container .button:armed { diff --git a/main/ui/src/main/resources/css/light_theme.css b/main/ui/src/main/resources/css/light_theme.css index 020b07a1e..f33837828 100644 --- a/main/ui/src/main/resources/css/light_theme.css +++ b/main/ui/src/main/resources/css/light_theme.css @@ -19,7 +19,7 @@ SCROLL_BAR_THUMB_HOVER: #B1B1B1; -fx-background-color: MAIN_BG; - -fx-text-fill: TEXT_FILL; + -fx-text-fill: TEXT_FILL; } /******************************************************************************* @@ -97,26 +97,32 @@ ******************************************************************************/ .tab-pane { - -fx-tab-min-height: 24; + -fx-tab-min-height: 2em; } + .tab-pane > .tab-header-area { -fx-padding: 6px 12px 0 12px; -fx-background-color: CONTROL_BORDER_FOCUSED, MAIN_BG; - -fx-background-insets: 0, 0 0 1 0; + -fx-background-insets: 0, 0 0 1px 0; } + .tab-pane > .tab-header-area > .headers-region > .tab { - -fx-text-fill: TEXT_FILL; - -fx-alignment: CENTER; - -fx-background-color: CONTROL_BORDER_NORMAL, CONTROL_BORDER_FOCUSED, MAIN_BG; - -fx-background-insets: 0, 1px 1px 0 1px, 1px; + -fx-background-color: CONTROL_BORDER_NORMAL, MAIN_BG; + -fx-background-insets: 0 0 1px 0, 1px; -fx-background-radius: 4px 4px 0 0; -fx-padding: 0.2em 0.4em 0.2em 0.4em; } + .tab-pane > .tab-header-area > .headers-region > .tab:selected { -fx-background-color: CONTROL_BORDER_FOCUSED, MAIN_BG; -fx-background-insets: 0, 1px 1px 0 1px; } +.tab-pane > .tab-header-area > .headers-region > .tab > .tab-container > .tab-label { + -fx-text-fill: TEXT_FILL; + -fx-alignment: CENTER; +} + /******************************************************************************* * * * SplitPane * @@ -139,7 +145,7 @@ ******************************************************************************/ .list-view { - -fx-background-color: CONTROL_BG_NORMAL; + -fx-background-color: CONTROL_BG_NORMAL; } .list-cell:selected { @@ -182,7 +188,7 @@ -fx-background-insets: 0; -fx-background-radius: 0; -fx-border-color: transparent CONTROL_BORDER_NORMAL transparent transparent; - -fx-border-width: 1; + -fx-border-width: 1; } .toolbar-container .button:armed { From 8d08d81f4572da79661fea8057cbf5982e17f679 Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Tue, 6 Aug 2019 17:02:06 +0200 Subject: [PATCH 086/264] more specific throws statement --- .../main/java/org/cryptomator/ui/fxapp/UpdateCheckerTask.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/ui/src/main/java/org/cryptomator/ui/fxapp/UpdateCheckerTask.java b/main/ui/src/main/java/org/cryptomator/ui/fxapp/UpdateCheckerTask.java index 461a04fc6..4d077a24c 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/fxapp/UpdateCheckerTask.java +++ b/main/ui/src/main/java/org/cryptomator/ui/fxapp/UpdateCheckerTask.java @@ -31,7 +31,7 @@ public class UpdateCheckerTask extends Task { } @Override - protected String call() throws Exception { + protected String call() throws IOException, InterruptedException { HttpResponse response = httpClient.send(checkForUpdatesRequest, HttpResponse.BodyHandlers.ofInputStream()); if (response.statusCode() == 200) { return processBody(response); From 04c45756b9c5f7c3595d073a8bbdbedc092f3237 Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Tue, 6 Aug 2019 17:02:21 +0200 Subject: [PATCH 087/264] removed unused imports --- .../java/org/cryptomator/ui/traymenu/FxApplicationStarter.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/main/ui/src/main/java/org/cryptomator/ui/traymenu/FxApplicationStarter.java b/main/ui/src/main/java/org/cryptomator/ui/traymenu/FxApplicationStarter.java index de4bbd046..15d23152f 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/traymenu/FxApplicationStarter.java +++ b/main/ui/src/main/java/org/cryptomator/ui/traymenu/FxApplicationStarter.java @@ -9,9 +9,7 @@ import org.slf4j.LoggerFactory; import javax.inject.Inject; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; -import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; -import java.util.concurrent.Future; @TrayMenuScoped public class FxApplicationStarter { From cb50b2011f0f9e210c1f1d3adf5906d025839b16 Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Tue, 6 Aug 2019 17:03:05 +0200 Subject: [PATCH 088/264] Lock remaining vaults on shutdown (references #838) --- .../cryptomator/ui/quit/QuitController.java | 106 ++++++++++++++---- main/ui/src/main/resources/fxml/quit.fxml | 3 +- 2 files changed, 87 insertions(+), 22 deletions(-) diff --git a/main/ui/src/main/java/org/cryptomator/ui/quit/QuitController.java b/main/ui/src/main/java/org/cryptomator/ui/quit/QuitController.java index 9a0f6c836..cae265e60 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/quit/QuitController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/quit/QuitController.java @@ -1,16 +1,24 @@ package org.cryptomator.ui.quit; -import javafx.beans.property.ObjectProperty; -import javafx.beans.property.SimpleObjectProperty; +import javafx.application.Platform; +import javafx.collections.ObservableList; +import javafx.concurrent.ScheduledService; +import javafx.concurrent.Task; import javafx.fxml.FXML; +import javafx.scene.control.Button; import javafx.scene.control.ContentDisplay; import javafx.stage.Stage; +import org.cryptomator.common.vaults.Vault; +import org.cryptomator.common.vaults.Volume; import org.cryptomator.ui.common.FxController; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.inject.Inject; import java.awt.desktop.QuitResponse; +import java.util.Iterator; +import java.util.List; +import java.util.concurrent.Executor; import java.util.concurrent.ExecutorService; @QuitScoped @@ -20,15 +28,16 @@ public class QuitController implements FxController { private final Stage window; private final QuitResponse response; + private final ObservableList unlockedVaults; private final ExecutorService executor; - private final ObjectProperty quitButtonState; + public Button lockAndQuitButton; @Inject - QuitController(@QuitWindow Stage window, QuitResponse response, ExecutorService executor) { + QuitController(@QuitWindow Stage window, QuitResponse response, ObservableList vaults, ExecutorService executor) { this.window = window; this.response = response; + this.unlockedVaults = vaults.filtered(Vault::isUnlocked); this.executor = executor; - this.quitButtonState = new SimpleObjectProperty<>(ContentDisplay.TEXT_ONLY); } @FXML @@ -39,26 +48,83 @@ public class QuitController implements FxController { } @FXML - public void quit() { - LOG.warn("Quit not yet implemented."); - window.close(); - response.cancelQuit(); + public void lockAndQuit() { + lockAndQuitButton.setDisable(true); + lockAndQuitButton.setContentDisplay(ContentDisplay.LEFT); + + Iterator toBeLocked = List.copyOf(unlockedVaults).iterator(); + ScheduledService lockAllService = new LockAllVaultsService(executor, toBeLocked); + lockAllService.setOnSucceeded(evt -> { + if (!toBeLocked.hasNext()) { + window.close(); + response.performQuit(); + } + }); + lockAllService.setOnFailed(evt -> { + lockAndQuitButton.setDisable(false); + lockAndQuitButton.setContentDisplay(ContentDisplay.TEXT_ONLY); + // TODO: show force lock or force quit scene (and DO NOT cancelQuit() here!) + response.cancelQuit(); + }); + lockAllService.start(); } - @FXML - public void forceQuit() { - LOG.warn("Force Quit not yet implemented."); - window.close(); - response.cancelQuit(); + /** + * @param vault The vault to lock + * @return Task that tries to lock the given vault gracefully. + */ + private Task createGracefulLockTask(Vault vault) { + Task task = new Task() { + @Override + protected Void call() throws Volume.VolumeException { + vault.lock(false); + LOG.info("Locked {}", vault.getDisplayableName()); + return null; + } + }; + task.setOnSucceeded(evt -> { + vault.setState(Vault.State.LOCKED); + }); + task.setOnFailed(evt -> { + LOG.warn("Failed to lock vault", vault); + }); + return task; } - /* Observable Properties */ - - public ObjectProperty quitButtonStateProperty() { - return quitButtonState; + /** + * @return Task that succeeds immediately + */ + private Task createNoopTask() { + return new Task<>() { + @Override + protected Void call() { + return null; + } + }; } + + private class LockAllVaultsService extends ScheduledService { - public ContentDisplay getQuitButtonState() { - return quitButtonState.get(); + private final Iterator vaultsToLock; + + public LockAllVaultsService(Executor executor, Iterator vaultsToLock) { + this.vaultsToLock = vaultsToLock; + setExecutor(executor); + setRestartOnFailure(false); + } + + @Override + protected Task createTask() { + assert Platform.isFxApplicationThread(); + if (vaultsToLock.hasNext()) { + return createGracefulLockTask(vaultsToLock.next()); + } else { + // This should be unreachable code, since vaultsToLock is only accessed on the FX App Thread. + // But if quitting the application takes longer for any reason, this service should shut down properly + reset(); + return createNoopTask(); + } + } } + } diff --git a/main/ui/src/main/resources/fxml/quit.fxml b/main/ui/src/main/resources/fxml/quit.fxml index 5e9f6017c..4806f82bc 100644 --- a/main/ui/src/main/resources/fxml/quit.fxml +++ b/main/ui/src/main/resources/fxml/quit.fxml @@ -23,8 +23,7 @@ - + diff --git a/main/ui/src/main/resources/fxml/unlock2.fxml b/main/ui/src/main/resources/fxml/unlock2.fxml index 741d4aefe..170dd3818 100644 --- a/main/ui/src/main/resources/fxml/unlock2.fxml +++ b/main/ui/src/main/resources/fxml/unlock2.fxml @@ -5,7 +5,6 @@ - @@ -14,21 +13,23 @@ xmlns:fx="http://javafx.com/fxml" fx:controller="org.cryptomator.ui.unlock.UnlockController" minWidth="300" + maxWidth="300" spacing="6"> - + + + - - - + + + + + + diff --git a/main/ui/src/main/resources/fxml/main_window.fxml b/main/ui/src/main/resources/fxml/main_window.fxml index e1dde4ffd..85414195e 100644 --- a/main/ui/src/main/resources/fxml/main_window.fxml +++ b/main/ui/src/main/resources/fxml/main_window.fxml @@ -1,6 +1,5 @@ - @@ -10,6 +9,7 @@ + - + @@ -34,7 +34,7 @@ + + + + + + + + + - + diff --git a/main/ui/src/main/resources/fxml/vault_options.fxml b/main/ui/src/main/resources/fxml/vault_options.fxml index 134786251..899a2cf8e 100644 --- a/main/ui/src/main/resources/fxml/vault_options.fxml +++ b/main/ui/src/main/resources/fxml/vault_options.fxml @@ -11,7 +11,7 @@ tabClosingPolicy="UNAVAILABLE" tabDragPolicy="FIXED"> - + @@ -19,7 +19,7 @@ - + diff --git a/main/ui/src/main/resources/fxml/vault_options_general.fxml b/main/ui/src/main/resources/fxml/vault_options_general.fxml index 377a6d89f..88ef91a2c 100644 --- a/main/ui/src/main/resources/fxml/vault_options_general.fxml +++ b/main/ui/src/main/resources/fxml/vault_options_general.fxml @@ -1,7 +1,7 @@ - + - - - - - - - + + diff --git a/main/ui/src/main/resources/fxml/vault_options.fxml b/main/ui/src/main/resources/fxml/vault_options.fxml index 899a2cf8e..43241912d 100644 --- a/main/ui/src/main/resources/fxml/vault_options.fxml +++ b/main/ui/src/main/resources/fxml/vault_options.fxml @@ -13,7 +13,7 @@ - + diff --git a/main/ui/src/main/resources/i18n/strings.properties b/main/ui/src/main/resources/i18n/strings.properties index 1f32b69a9..bc6403b2f 100644 --- a/main/ui/src/main/resources/i18n/strings.properties +++ b/main/ui/src/main/resources/i18n/strings.properties @@ -53,21 +53,22 @@ preferences.general.theme=Look & Feel preferences.general.startHidden=Hide window when starting Cryptomator preferences.general.debugLogging=Enable debug logging preferences.general.volumeType=Volume Type +## Volume +preferences.volume=Virtual Drive ## Updates preferences.updates=Updates preferences.updates.autoUpdateCheck=Check for updates automatically preferences.updates.checkNowBtn=Check Now -## Volume -preferences.volume=Virtual Drive # Main Window main.closeBtn.tooltip=Close -main.settingsBtn.tooltip=Settings +main.preferencesBtn.tooltip=Preferences vaultlist.emptyList.onboardingInstruction=Click here to add a vault ## Vault Detail +vaultDetail.lockedStatus=LOCKED +vaultDetail.unlockedStatus=UNLOCKED vaultDetail.unlockBtn=Unlock vaultDetail.lockBtn=Lock -vaultDetail.optionsBtn=Options vaultDetail.accessLocation=access location # Vault Options diff --git a/main/ui/src/main/resources/i18n/strings_en.properties b/main/ui/src/main/resources/i18n/strings_en.properties index afde3b57c..e69de29bb 100644 --- a/main/ui/src/main/resources/i18n/strings_en.properties +++ b/main/ui/src/main/resources/i18n/strings_en.properties @@ -1,19 +0,0 @@ -addvaultwizard.existing.instruction=Please choose the masterkey.cryptomator file of your existing vault. The directory contain it will be displayed. -addvaultwizard.existing.filePickerTitle=Open Masterkey File -addvaultwizard.new.insertName=Please enter a name for the vault. -addvaultwizard.new.selectLocation=Please pick a directory where your vault is stored: -addvaultwizard.new.directoryPickerTitle=Select Directory -addvaultwizard.new.enterPassword=Please enter a Password for your vault: -addvaultwizard.new.reenterPassword=Please retype the password: -main.closeBtn.tooltip=Close -main.settingsBtn.tooltip=Settings -preferences.autoUpdateCheck=Check for updates automatically -preferences.debugLogging=Enable debug logging -preferences.startHidden=Hide window when starting Cryptomator -preferences.theme=Look & Feel -preferences.volume=Virtual Drive -preferences.volumeType=Volume type -vaultlist.emptyList.onboardingInstruction=Click here to add a vault -vaultOptions.mount.readonly=Read-Only -vaultOptions.mount.driveName=Drive Name -vaultOptions.mount.customMountFlags=Custom Mount Flags From 8c9424510278705c7c92c7a505ba9bcfb8a05ff0 Mon Sep 17 00:00:00 2001 From: Tobias Hagemann Date: Sun, 25 Aug 2019 00:34:16 +0200 Subject: [PATCH 132/264] updated menu item stylings of choicebox, updated window sizes & disabled resizable of preferences and vault options --- .../ui/preferences/PreferencesModule.java | 3 +-- .../ui/vaultoptions/VaultOptionsModule.java | 4 +--- main/ui/src/main/resources/css/dark_theme.css | 18 +++++++++++++++++- main/ui/src/main/resources/css/light_theme.css | 18 +++++++++++++++++- .../src/main/resources/fxml/preferences.fxml | 2 +- .../src/main/resources/fxml/vault_options.fxml | 2 +- 6 files changed, 38 insertions(+), 9 deletions(-) diff --git a/main/ui/src/main/java/org/cryptomator/ui/preferences/PreferencesModule.java b/main/ui/src/main/java/org/cryptomator/ui/preferences/PreferencesModule.java index c968ea230..a2e175b89 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/preferences/PreferencesModule.java +++ b/main/ui/src/main/java/org/cryptomator/ui/preferences/PreferencesModule.java @@ -35,8 +35,7 @@ abstract class PreferencesModule { static Stage provideStage(ResourceBundle resourceBundle) { Stage stage = new Stage(); stage.setTitle(resourceBundle.getString("preferences.title")); - stage.setMinWidth(400); - stage.setMinHeight(300); + stage.setResizable(false); return stage; } diff --git a/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsModule.java b/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsModule.java index aa6d42ae2..499058de7 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsModule.java +++ b/main/ui/src/main/java/org/cryptomator/ui/vaultoptions/VaultOptionsModule.java @@ -39,9 +39,7 @@ abstract class VaultOptionsModule { static Stage provideStage(@MainWindow Stage owner, @VaultOptionsWindow Vault vault, ResourceBundle resourceBundle) { Stage stage = new Stage(); stage.setTitle(vault.getDisplayableName()); - // stage.setTitle(resourceBundle.getString("vaultOptions.title")); - stage.setMinWidth(400); - stage.setMinHeight(300); + stage.setResizable(false); stage.initStyle(StageStyle.DECORATED); stage.initModality(Modality.WINDOW_MODAL); stage.initOwner(owner); diff --git a/main/ui/src/main/resources/css/dark_theme.css b/main/ui/src/main/resources/css/dark_theme.css index 8cc599727..6732c1a91 100644 --- a/main/ui/src/main/resources/css/dark_theme.css +++ b/main/ui/src/main/resources/css/dark_theme.css @@ -579,6 +579,7 @@ -fx-background-insets: 0, 1px; -fx-background-radius: 4px; -fx-padding: 0.2em 0 0.2em 0; + -fx-translate-x: -1.4em; } .context-menu { @@ -590,7 +591,22 @@ } .menu-item:focused { - -fx-background-color: CONTROL_BG_ARMED; + -fx-background-color: transparent, CONTROL_BG_ARMED; + -fx-background-insets: 0, 0 1px 0 1px; +} + +.menu-item > .left-container { + -fx-padding: 0.5em 0.25em 0.5em 0.5em; +} + +.menu-item > .label { + -fx-padding: 1px 0.5em 1px 0.5em; +} + +.radio-menu-item:checked > .left-container > .radio { + -fx-background-color: TEXT_FILL; + -fx-shape: "M-1,4, L-1,5.5 L3.5,8.5 L9,0 L9,-1 L7,-1 L3,6 L1,4 Z"; + -fx-scale-shape: false; } /******************************************************************************* diff --git a/main/ui/src/main/resources/css/light_theme.css b/main/ui/src/main/resources/css/light_theme.css index 2a7383913..337d64c9a 100644 --- a/main/ui/src/main/resources/css/light_theme.css +++ b/main/ui/src/main/resources/css/light_theme.css @@ -579,6 +579,7 @@ -fx-background-insets: 0, 1px; -fx-background-radius: 4px; -fx-padding: 0.2em 0 0.2em 0; + -fx-translate-x: -1.4em; } .context-menu { @@ -590,7 +591,22 @@ } .menu-item:focused { - -fx-background-color: CONTROL_BG_ARMED; + -fx-background-color: transparent, CONTROL_BG_ARMED; + -fx-background-insets: 0, 0 1px 0 1px; +} + +.menu-item > .left-container { + -fx-padding: 0.5em 0.25em 0.5em 0.5em; +} + +.menu-item > .label { + -fx-padding: 1px 0.5em 1px 0.5em; +} + +.radio-menu-item:checked > .left-container > .radio { + -fx-background-color: TEXT_FILL; + -fx-shape: "M-1,4, L-1,5.5 L3.5,8.5 L9,0 L9,-1 L7,-1 L3,6 L1,4 Z"; + -fx-scale-shape: false; } /******************************************************************************* diff --git a/main/ui/src/main/resources/fxml/preferences.fxml b/main/ui/src/main/resources/fxml/preferences.fxml index 652ca9671..34ea44235 100644 --- a/main/ui/src/main/resources/fxml/preferences.fxml +++ b/main/ui/src/main/resources/fxml/preferences.fxml @@ -7,7 +7,7 @@ xmlns:fx="http://javafx.com/fxml" fx:id="tabPane" fx:controller="org.cryptomator.ui.preferences.PreferencesController" - side="TOP" + minWidth="400" tabClosingPolicy="UNAVAILABLE" tabDragPolicy="FIXED"> diff --git a/main/ui/src/main/resources/fxml/vault_options.fxml b/main/ui/src/main/resources/fxml/vault_options.fxml index 43241912d..20910a66e 100644 --- a/main/ui/src/main/resources/fxml/vault_options.fxml +++ b/main/ui/src/main/resources/fxml/vault_options.fxml @@ -7,7 +7,7 @@ xmlns:fx="http://javafx.com/fxml" fx:id="tabPane" fx:controller="org.cryptomator.ui.vaultoptions.VaultOptionsController" - side="TOP" + minWidth="400" tabClosingPolicy="UNAVAILABLE" tabDragPolicy="FIXED"> From d58ad1e0a2e7b6eb3770caa8065e5f7e513e640b Mon Sep 17 00:00:00 2001 From: Tobias Hagemann Date: Mon, 26 Aug 2019 00:28:01 +0200 Subject: [PATCH 133/264] updated add vault wizard layout & stylings --- .../ui/addvaultwizard/AddVaultModule.java | 6 +-- .../CreateNewVaultPasswordController.java | 12 +++-- .../ui/controls/FontAwesome5Icon.java | 2 + main/ui/src/main/resources/css/dark_theme.css | 26 +++++++-- .../ui/src/main/resources/css/light_theme.css | 26 +++++++-- .../resources/fxml/addvault_existing.fxml | 8 ++- .../resources/fxml/addvault_new_location.fxml | 37 +++++++------ .../resources/fxml/addvault_new_name.fxml | 9 +++- .../resources/fxml/addvault_new_password.fxml | 53 +++++++++++-------- .../main/resources/fxml/addvault_welcome.fxml | 31 ++++++++--- .../main/resources/i18n/strings.properties | 33 ++++++------ 11 files changed, 162 insertions(+), 81 deletions(-) diff --git a/main/ui/src/main/java/org/cryptomator/ui/addvaultwizard/AddVaultModule.java b/main/ui/src/main/java/org/cryptomator/ui/addvaultwizard/AddVaultModule.java index 55a278c94..4771b1719 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/addvaultwizard/AddVaultModule.java +++ b/main/ui/src/main/java/org/cryptomator/ui/addvaultwizard/AddVaultModule.java @@ -37,10 +37,10 @@ public abstract class AddVaultModule { @Provides @AddVaultWizard @AddVaultWizardScoped - static Stage provideStage(@MainWindow Stage owner) { + static Stage provideStage(@MainWindow Stage owner, ResourceBundle resourceBundle) { Stage stage = new Stage(); - stage.setMinWidth(500); - stage.setMinHeight(500); + stage.setTitle(resourceBundle.getString("addvaultwizard.title")); + stage.setResizable(false); stage.initStyle(StageStyle.DECORATED); stage.initModality(Modality.WINDOW_MODAL); stage.initOwner(owner); diff --git a/main/ui/src/main/java/org/cryptomator/ui/addvaultwizard/CreateNewVaultPasswordController.java b/main/ui/src/main/java/org/cryptomator/ui/addvaultwizard/CreateNewVaultPasswordController.java index 67615adea..890412ad4 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/addvaultwizard/CreateNewVaultPasswordController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/addvaultwizard/CreateNewVaultPasswordController.java @@ -11,10 +11,10 @@ import javafx.collections.ObservableList; import javafx.fxml.FXML; import javafx.scene.Scene; import javafx.scene.control.Button; +import javafx.scene.control.CheckBox; import javafx.scene.control.Label; import javafx.scene.layout.HBox; import javafx.scene.layout.Region; -import javafx.scene.shape.Rectangle; import javafx.stage.Stage; import org.cryptomator.common.settings.VaultSettings; import org.cryptomator.common.vaults.Vault; @@ -22,6 +22,7 @@ import org.cryptomator.common.vaults.VaultFactory; import org.cryptomator.ui.common.FxController; import org.cryptomator.ui.common.FxmlFile; import org.cryptomator.ui.common.FxmlScene; +import org.cryptomator.ui.controls.FontAwesome5IconView; import org.cryptomator.ui.controls.SecPasswordField; import org.cryptomator.ui.util.PasswordStrengthUtil; import org.fxmisc.easybind.EasyBind; @@ -55,9 +56,10 @@ public class CreateNewVaultPasswordController implements FxController { public Region passwordStrengthLevel4; public Label passwordStrengthLabel; public HBox passwordMatchBox; - public Rectangle checkmark; - public Rectangle cross; + public FontAwesome5IconView checkmark; + public FontAwesome5IconView cross; public Label passwordMatchLabel; + public CheckBox finalConfirmationCheckbox; @Inject CreateNewVaultPasswordController(@AddVaultWizard Stage window, @FxmlScene(FxmlFile.ADDVAULT_NEW_LOCATION) Lazy previousScene, StringProperty vaultName, ObjectProperty vaultPath, ObservableList vaults, VaultFactory vaultFactory, ResourceBundle resourceBundle, PasswordStrengthUtil strengthRater) { @@ -80,11 +82,13 @@ public class CreateNewVaultPasswordController implements FxController { BooleanBinding passwordsMatch = Bindings.createBooleanBinding(() -> CharSequence.compare(passwordField.getCharacters(), reenterField.getCharacters()) == 0, passwordField.textProperty(), reenterField.textProperty()); BooleanBinding reenterFieldNotEmpty = reenterField.textProperty().isNotEmpty(); //disable the finish button when passwords do not match or one is empty - finishButton.disableProperty().bind(reenterFieldNotEmpty.not().or(passwordsMatch.not())); + finishButton.disableProperty().bind(reenterFieldNotEmpty.not().or(passwordsMatch.not()).or(finalConfirmationCheckbox.selectedProperty().not())); //make match indicator invisible when passwords do not match or one is empty passwordMatchBox.visibleProperty().bind(reenterFieldNotEmpty); checkmark.visibleProperty().bind(passwordsMatch.and(reenterFieldNotEmpty)); + checkmark.managedProperty().bind(checkmark.visibleProperty()); cross.visibleProperty().bind(passwordsMatch.not().and(reenterFieldNotEmpty)); + cross.managedProperty().bind(cross.visibleProperty()); passwordMatchLabel.textProperty().bind(Bindings.when(passwordsMatch.and(reenterFieldNotEmpty)).then(resourceBundle.getString("addvaultwizard.new.passwordsMatch")).otherwise(resourceBundle.getString("addvaultwizard.new.passwordsDoNotMatch"))); //bindsings for the password strength indicator diff --git a/main/ui/src/main/java/org/cryptomator/ui/controls/FontAwesome5Icon.java b/main/ui/src/main/java/org/cryptomator/ui/controls/FontAwesome5Icon.java index da29581b3..3b350929f 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/controls/FontAwesome5Icon.java +++ b/main/ui/src/main/java/org/cryptomator/ui/controls/FontAwesome5Icon.java @@ -5,6 +5,7 @@ package org.cryptomator.ui.controls; */ public enum FontAwesome5Icon { ANCHOR("\uF13D"), // + CHECK("\uF00C"), // CIRCLE("\uF111"), // COG("\uF013"), // COGS("\uF085"), // @@ -15,6 +16,7 @@ public enum FontAwesome5Icon { LOCK_OPEN_ALT("\uF3C2"), // MINUS("\uF068"), // PLUS("\uF067"), // + SEARCH("\uF002"), // SPINNER("\uF110"), // SYNC("\uF021"), // TIMES("\uF00D"), // diff --git a/main/ui/src/main/resources/css/dark_theme.css b/main/ui/src/main/resources/css/dark_theme.css index 6732c1a91..9379dbbff 100644 --- a/main/ui/src/main/resources/css/dark_theme.css +++ b/main/ui/src/main/resources/css/dark_theme.css @@ -38,10 +38,6 @@ -fx-text-fill: TEXT_FILL; } -.glyph-icon { - -fx-fill: TEXT_FILL; -} - /******************************************************************************* * * * Labels * @@ -52,10 +48,28 @@ -fx-text-fill: TEXT_FILL; } +.label-secondary { + -fx-text-fill: TEXT_FILL_SECONDARY; +} + .text-flow > * { -fx-fill: TEXT_FILL; } +/******************************************************************************* + * * + * Glyph Icons * + * * + ******************************************************************************/ + +.glyph-icon { + -fx-fill: TEXT_FILL; +} + +.glyph-icon-secondary { + -fx-fill: TEXT_FILL_SECONDARY; +} + /******************************************************************************* * * * Main Window * @@ -463,6 +477,10 @@ -fx-background-color: CONTROL_PRIMARY_BORDER_DISABLED, CONTROL_PRIMARY_BG_DISABLED; } +.button:disabled .glyph-icon { + -fx-fill: TEXT_FILL_SECONDARY; +} + .button:default .glyph-icon { -fx-fill: TEXT_FILL_WHITE; } diff --git a/main/ui/src/main/resources/css/light_theme.css b/main/ui/src/main/resources/css/light_theme.css index 337d64c9a..1e97f6921 100644 --- a/main/ui/src/main/resources/css/light_theme.css +++ b/main/ui/src/main/resources/css/light_theme.css @@ -38,10 +38,6 @@ -fx-text-fill: TEXT_FILL; } -.glyph-icon { - -fx-fill: TEXT_FILL; -} - /******************************************************************************* * * * Labels * @@ -52,10 +48,28 @@ -fx-text-fill: TEXT_FILL; } +.label-secondary { + -fx-text-fill: TEXT_FILL_SECONDARY; +} + .text-flow > * { -fx-fill: TEXT_FILL; } +/******************************************************************************* + * * + * Glyph Icons * + * * + ******************************************************************************/ + +.glyph-icon { + -fx-fill: TEXT_FILL; +} + +.glyph-icon-secondary { + -fx-fill: TEXT_FILL_SECONDARY; +} + /******************************************************************************* * * * Main Window * @@ -463,6 +477,10 @@ -fx-background-color: CONTROL_PRIMARY_BORDER_DISABLED, CONTROL_PRIMARY_BG_DISABLED; } +.button:disabled .glyph-icon { + -fx-fill: TEXT_FILL_SECONDARY; +} + .button:default .glyph-icon { -fx-fill: TEXT_FILL_WHITE; } diff --git a/main/ui/src/main/resources/fxml/addvault_existing.fxml b/main/ui/src/main/resources/fxml/addvault_existing.fxml index bf78ab703..e50ab48af 100644 --- a/main/ui/src/main/resources/fxml/addvault_existing.fxml +++ b/main/ui/src/main/resources/fxml/addvault_existing.fxml @@ -9,20 +9,24 @@ + - - - - - - + - - - + diff --git a/main/ui/src/main/resources/fxml/vault_detail.fxml b/main/ui/src/main/resources/fxml/vault_detail.fxml index da5cfd8e9..90882cf9f 100644 --- a/main/ui/src/main/resources/fxml/vault_detail.fxml +++ b/main/ui/src/main/resources/fxml/vault_detail.fxml @@ -71,8 +71,10 @@ - + + + diff --git a/main/ui/src/main/resources/fxml/unlock_success.fxml b/main/ui/src/main/resources/fxml/unlock_success.fxml index 34dade046..f9e43c458 100644 --- a/main/ui/src/main/resources/fxml/unlock_success.fxml +++ b/main/ui/src/main/resources/fxml/unlock_success.fxml @@ -4,7 +4,6 @@ - @@ -12,19 +11,20 @@ xmlns:fx="http://javafx.com/fxml" fx:controller="org.cryptomator.ui.unlock.UnlockSuccessController" minWidth="300" + maxWidth="300" spacing="6"> - + + - + - - - + - + diff --git a/main/ui/src/main/resources/fxml/unlock_success.fxml b/main/ui/src/main/resources/fxml/unlock_success.fxml index f9e43c458..9d1b539c6 100644 --- a/main/ui/src/main/resources/fxml/unlock_success.fxml +++ b/main/ui/src/main/resources/fxml/unlock_success.fxml @@ -4,9 +4,12 @@ + + + - + + + + + + + + + + + + + - + From 638dac9cb6ca7b7bf01e0887f2607f2da6382c30 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Tue, 27 Aug 2019 13:45:53 +0200 Subject: [PATCH 151/264] adding missing acces location text --- .../common/vaults/DokanyVolume.java | 14 ++++++++++---- .../cryptomator/common/vaults/FuseVolume.java | 8 ++++++-- .../org/cryptomator/common/vaults/Vault.java | 18 ++++++++++++++++++ .../org/cryptomator/common/vaults/Volume.java | 4 ++++ .../common/vaults/WebDavVolume.java | 8 ++++++++ .../src/main/resources/fxml/vault_detail.fxml | 2 +- 6 files changed, 47 insertions(+), 7 deletions(-) diff --git a/main/commons/src/main/java/org/cryptomator/common/vaults/DokanyVolume.java b/main/commons/src/main/java/org/cryptomator/common/vaults/DokanyVolume.java index 87009dcf7..c20538e5d 100644 --- a/main/commons/src/main/java/org/cryptomator/common/vaults/DokanyVolume.java +++ b/main/commons/src/main/java/org/cryptomator/common/vaults/DokanyVolume.java @@ -30,6 +30,7 @@ public class DokanyVolume implements Volume { private final MountFactory mountFactory; private final WindowsDriveLetters windowsDriveLetters; private Mount mount; + private Path mountPoint; @Inject public DokanyVolume(VaultSettings vaultSettings, ExecutorService executorService, WindowsDriveLetters windowsDriveLetters) { @@ -45,19 +46,19 @@ public class DokanyVolume implements Volume { @Override public void mount(CryptoFileSystem fs, String mountFlags) throws VolumeException, IOException { - Path mountPath = getMountPoint(); + this.mountPoint = determineMountPoint(); String mountName = vaultSettings.mountName().get(); try { - this.mount = mountFactory.mount(fs.getPath("/"), mountPath, mountName, FS_TYPE_NAME, mountFlags.strip()); + this.mount = mountFactory.mount(fs.getPath("/"), mountPoint, mountName, FS_TYPE_NAME, mountFlags.strip()); } catch (MountFailedException e) { if (vaultSettings.getIndividualMountPath().isPresent()) { - LOG.warn("Failed to mount vault into {}. Is this directory currently accessed by another process (e.g. Windows Explorer)?", mountPath); + LOG.warn("Failed to mount vault into {}. Is this directory currently accessed by another process (e.g. Windows Explorer)?", mountPoint); } throw new VolumeException("Unable to mount Filesystem", e); } } - private Path getMountPoint() throws VolumeException, IOException { + private Path determineMountPoint() throws VolumeException, IOException { Optional optionalCustomMountPoint = vaultSettings.getIndividualMountPath(); if (optionalCustomMountPoint.isPresent()) { Path customMountPoint = Paths.get(optionalCustomMountPoint.get()); @@ -99,6 +100,11 @@ public class DokanyVolume implements Volume { mount.close(); } + @Override + public Optional getMountPointSafe() { + return Optional.ofNullable(mountPoint); + } + public static boolean isSupportedStatic() { return MountFactory.isApplicable(); } diff --git a/main/commons/src/main/java/org/cryptomator/common/vaults/FuseVolume.java b/main/commons/src/main/java/org/cryptomator/common/vaults/FuseVolume.java index e5330a1ad..05663d519 100644 --- a/main/commons/src/main/java/org/cryptomator/common/vaults/FuseVolume.java +++ b/main/commons/src/main/java/org/cryptomator/common/vaults/FuseVolume.java @@ -100,8 +100,7 @@ public class FuseVolume implements Volume { try { Mounter mounter = FuseMountFactory.getMounter(); EnvironmentVariables envVars = EnvironmentVariables.create() // - .withFlags(splitFlags(mountFlags)) - .withMountPoint(mountPoint) // + .withFlags(splitFlags(mountFlags)).withMountPoint(mountPoint) // .build(); this.fuseMnt = mounter.mount(root, envVars); } catch (CommandFailedException e) { @@ -166,6 +165,11 @@ public class FuseVolume implements Volume { return FuseVolume.isSupportedStatic(); } + @Override + public Optional getMountPointSafe() { + return Optional.ofNullable(mountPoint); + } + public static boolean isSupportedStatic() { return (SystemUtils.IS_OS_MAC_OSX || SystemUtils.IS_OS_LINUX) && FuseMountFactory.isFuseSupported(); } diff --git a/main/commons/src/main/java/org/cryptomator/common/vaults/Vault.java b/main/commons/src/main/java/org/cryptomator/common/vaults/Vault.java index c5bb75b5a..981afbee8 100644 --- a/main/commons/src/main/java/org/cryptomator/common/vaults/Vault.java +++ b/main/commons/src/main/java/org/cryptomator/common/vaults/Vault.java @@ -58,6 +58,7 @@ public class Vault { private final StringBinding defaultMountFlags; private final AtomicReference cryptoFileSystem = new AtomicReference<>(); private final ObjectProperty state = new SimpleObjectProperty(State.LOCKED); + private final ObjectProperty accessPoint = new SimpleObjectProperty<>(Path.of("")); private final StringBinding displayableName; private final StringBinding displayablePath; private final BooleanBinding locked; @@ -81,6 +82,7 @@ public class Vault { this.locked = Bindings.createBooleanBinding(this::isLocked, state); this.processing = Bindings.createBooleanBinding(this::isProcessing, state); this.unlocked = Bindings.createBooleanBinding(this::isUnlocked, state); + this.state.addListener(this::setAccessPoint); } // ****************************************************************************** @@ -219,6 +221,22 @@ public class Vault { return p.getFileName().toString(); } + public ObjectProperty accessPointProperty() { + return accessPoint; + } + + public Path getAccessPoint() { + return accessPoint.get(); + } + + private void setAccessPoint(Observable obs) { + if (this.getState() == State.UNLOCKED) { + accessPoint.setValue(volume.getMountPointSafe().get()); + } else { + accessPoint.setValue(Path.of("")); + } + } + public StringBinding displayablePathProperty() { return displayablePath; } diff --git a/main/commons/src/main/java/org/cryptomator/common/vaults/Volume.java b/main/commons/src/main/java/org/cryptomator/common/vaults/Volume.java index 6b36d6d45..21515a8f0 100644 --- a/main/commons/src/main/java/org/cryptomator/common/vaults/Volume.java +++ b/main/commons/src/main/java/org/cryptomator/common/vaults/Volume.java @@ -4,6 +4,8 @@ import org.cryptomator.common.settings.VolumeImpl; import org.cryptomator.cryptofs.CryptoFileSystem; import java.io.IOException; +import java.nio.file.Path; +import java.util.Optional; import java.util.stream.Stream; /** @@ -28,6 +30,8 @@ public interface Volume { void unmount() throws VolumeException; + Optional getMountPointSafe(); + // optional forced unmounting: default boolean supportsForcedUnmount() { diff --git a/main/commons/src/main/java/org/cryptomator/common/vaults/WebDavVolume.java b/main/commons/src/main/java/org/cryptomator/common/vaults/WebDavVolume.java index ee682c9f2..6ff43a6b6 100644 --- a/main/commons/src/main/java/org/cryptomator/common/vaults/WebDavVolume.java +++ b/main/commons/src/main/java/org/cryptomator/common/vaults/WebDavVolume.java @@ -13,6 +13,8 @@ import javax.inject.Inject; import javax.inject.Provider; import java.net.InetAddress; import java.net.UnknownHostException; +import java.nio.file.Path; +import java.util.Optional; public class WebDavVolume implements Volume { @@ -25,6 +27,7 @@ public class WebDavVolume implements Volume { private WebDavServer server; private WebDavServletController servlet; private Mounter.Mount mount; + private Path mountPoint; @Inject public WebDavVolume(Provider serverProvider, VaultSettings vaultSettings, Settings settings) { @@ -93,6 +96,11 @@ public class WebDavVolume implements Volume { cleanup(); } + @Override + public Optional getMountPointSafe() { + return Optional.ofNullable(mountPoint); + } + private String getLocalhostAliasOrNull() { try { InetAddress alias = InetAddress.getByName(LOCALHOST_ALIAS); diff --git a/main/ui/src/main/resources/fxml/vault_detail.fxml b/main/ui/src/main/resources/fxml/vault_detail.fxml index d5349a562..ffff26336 100644 --- a/main/ui/src/main/resources/fxml/vault_detail.fxml +++ b/main/ui/src/main/resources/fxml/vault_detail.fxml @@ -57,7 +57,7 @@