Browse Source

Reworked implemenation by using dagger now:
* create and inject QuitResponse container
* QuitComponent manges now if quit window needs to be created
* controller only handles the most recent QuitResponse

Armin Schrenk 4 years ago
parent
commit
c6b786a771

+ 12 - 33
main/ui/src/main/java/org/cryptomator/ui/fxapp/FxApplication.java

@@ -26,13 +26,12 @@ import javafx.application.Application;
 import javafx.application.Platform;
 import javafx.beans.binding.Bindings;
 import javafx.beans.binding.BooleanBinding;
-import javafx.beans.property.ObjectProperty;
-import javafx.beans.property.SimpleObjectProperty;
 import javafx.beans.value.ObservableValue;
 import javafx.collections.ObservableSet;
 import javafx.stage.Stage;
 import java.awt.desktop.QuitResponse;
 import java.util.Optional;
+import java.util.concurrent.atomic.AtomicReference;
 
 @FxApplicationScoped
 public class FxApplication extends Application {
@@ -42,32 +41,29 @@ public class FxApplication extends Application {
 	private final Settings settings;
 	private final Lazy<MainWindowComponent> mainWindow;
 	private final Lazy<PreferencesComponent> preferencesWindow;
+	private final Lazy<QuitComponent> quitWindow;
 	private final Provider<UnlockComponent.Builder> unlockWindowBuilderProvider;
-	private final Provider<QuitComponent.Builder> quitWindowBuilderProvider;
 	private final Optional<TrayIntegrationProvider> trayIntegration;
 	private final Optional<UiAppearanceProvider> appearanceProvider;
 	private final VaultService vaultService;
 	private final LicenseHolder licenseHolder;
 	private final BooleanBinding hasVisibleStages;
 	private final UiAppearanceListener systemInterfaceThemeListener = this::systemInterfaceThemeChanged;
-
-	private volatile boolean quitDialogueIsShowing;
-	private ObjectProperty<Stage> quitStage;
+	private final AtomicReference<QuitResponse> quitResponse;
 
 	@Inject
-	FxApplication(Settings settings, Lazy<MainWindowComponent> mainWindow, Lazy<PreferencesComponent> preferencesWindow, Provider<UnlockComponent.Builder> unlockWindowBuilderProvider, Provider<QuitComponent.Builder> quitWindowBuilderProvider, Optional<TrayIntegrationProvider> trayIntegration, Optional<UiAppearanceProvider> appearanceProvider, VaultService vaultService, LicenseHolder licenseHolder, ObservableSet<Stage> visibleStages) {
+	FxApplication(Settings settings, Lazy<MainWindowComponent> mainWindow, Lazy<PreferencesComponent> preferencesWindow, Provider<UnlockComponent.Builder> unlockWindowBuilderProvider, Lazy<QuitComponent> quitWindow, Optional<TrayIntegrationProvider> trayIntegration, Optional<UiAppearanceProvider> appearanceProvider, VaultService vaultService, LicenseHolder licenseHolder, ObservableSet<Stage> visibleStages, AtomicReference<QuitResponse> quitResponse) {
 		this.settings = settings;
 		this.mainWindow = mainWindow;
 		this.preferencesWindow = preferencesWindow;
 		this.unlockWindowBuilderProvider = unlockWindowBuilderProvider;
-		this.quitWindowBuilderProvider = quitWindowBuilderProvider;
+		this.quitWindow = quitWindow;
 		this.trayIntegration = trayIntegration;
 		this.appearanceProvider = appearanceProvider;
 		this.vaultService = vaultService;
 		this.licenseHolder = licenseHolder;
 		this.hasVisibleStages = Bindings.isNotEmpty(visibleStages);
-		this.quitDialogueIsShowing = false;
-		this.quitStage = new SimpleObjectProperty<>(null);
+		this.quitResponse = quitResponse;
 	}
 
 	public void start() {
@@ -114,29 +110,12 @@ public class FxApplication extends Application {
 		});
 	}
 
-	public synchronized void showQuitWindow(QuitResponse response) {
-		//TODO: manage a list of quit responses and execute for all the same actions?
-		if (quitDialogueIsShowing) {
-			if (quitStage.isNotNull().get()) {
-				Platform.runLater(() -> {
-					quitStage.get().requestFocus();
-					LOG.debug("Focus QuitWindow");
-				});
-			}
-		} else {
-			quitDialogueIsShowing = true;
-			Platform.runLater(() -> {
-				var window = quitWindowBuilderProvider.get().quitResponse(response).build().showQuitWindow();
-				quitStage.set(window);
-				var originalListener = window.getOnCloseRequest();
-				window.setOnCloseRequest(windowEvent -> {
-					originalListener.handle(windowEvent);
-					quitStage.set(null);
-				});
-				LOG.debug("Showing QuitWindow");
-			});
-		}
-
+	public void showQuitWindow(QuitResponse response) {
+		quitResponse.set(response);
+		Platform.runLater(() -> {
+			quitWindow.get().showQuitWindow();
+			LOG.debug("Showing QuitWindow");
+		});
 	}
 
 	public VaultService getVaultService() {

+ 12 - 0
main/ui/src/main/java/org/cryptomator/ui/fxapp/FxApplicationModule.java

@@ -22,15 +22,23 @@ import javafx.collections.FXCollections;
 import javafx.collections.ObservableSet;
 import javafx.scene.image.Image;
 import javafx.stage.Stage;
+import java.awt.desktop.QuitResponse;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.UncheckedIOException;
 import java.util.Collections;
 import java.util.List;
+import java.util.concurrent.atomic.AtomicReference;
 
 @Module(includes = {UpdateCheckerModule.class}, subcomponents = {MainWindowComponent.class, PreferencesComponent.class, UnlockComponent.class, QuitComponent.class, ErrorComponent.class})
 abstract class FxApplicationModule {
 
+	@Provides
+	@FxApplicationScoped
+	static AtomicReference<QuitResponse> provideQuitResponse() {
+		return new AtomicReference<>();
+	}
+
 	@Provides
 	@FxApplicationScoped
 	static ObservableSet<Stage> provideVisibleStages() {
@@ -88,4 +96,8 @@ abstract class FxApplicationModule {
 		return builder.build();
 	}
 
+	@Provides
+	static QuitComponent provideQuitComponent(QuitComponent.Builder builder) {
+		return builder.build();
+	}
 }

+ 12 - 7
main/ui/src/main/java/org/cryptomator/ui/quit/QuitComponent.java

@@ -5,15 +5,14 @@
  *******************************************************************************/
 package org.cryptomator.ui.quit;
 
-import dagger.BindsInstance;
 import dagger.Lazy;
 import dagger.Subcomponent;
 import org.cryptomator.ui.common.FxmlFile;
 import org.cryptomator.ui.common.FxmlScene;
 
+import javafx.beans.property.ObjectProperty;
 import javafx.scene.Scene;
 import javafx.stage.Stage;
-import java.awt.desktop.QuitResponse;
 
 @QuitScoped
 @Subcomponent(modules = {QuitModule.class})
@@ -25,9 +24,18 @@ public interface QuitComponent {
 	@FxmlScene(FxmlFile.QUIT)
 	Lazy<Scene> scene();
 
+	ObjectProperty<Stage> provideStageProperty();
+
 	default Stage showQuitWindow() {
-		Stage stage = window();
-		stage.setScene(scene().get());
+		var stageProperty = provideStageProperty();
+		Stage stage;
+		if (stageProperty.isNull().get()) {
+			stage = window();
+			stage.setScene(scene().get());
+			stageProperty.set(stage);
+		} else {
+			stage = stageProperty.get();
+		}
 		stage.show();
 		stage.requestFocus();
 		return stage;
@@ -36,9 +44,6 @@ public interface QuitComponent {
 	@Subcomponent.Builder
 	interface Builder {
 
-		@BindsInstance
-		Builder quitResponse(QuitResponse response);
-
 		QuitComponent build();
 	}
 

+ 11 - 8
main/ui/src/main/java/org/cryptomator/ui/quit/QuitController.java

@@ -16,6 +16,7 @@ import javafx.stage.Stage;
 import java.awt.desktop.QuitResponse;
 import java.util.Collection;
 import java.util.concurrent.ExecutorService;
+import java.util.concurrent.atomic.AtomicReference;
 import java.util.stream.Collectors;
 
 @QuitScoped
@@ -24,26 +25,28 @@ public class QuitController implements FxController {
 	private static final Logger LOG = LoggerFactory.getLogger(QuitController.class);
 
 	private final Stage window;
-	private final QuitResponse response;
 	private final ObservableList<Vault> unlockedVaults;
 	private final ExecutorService executorService;
 	private final VaultService vaultService;
+	private final AtomicReference<QuitResponse> quitResponse;
 	public Button lockAndQuitButton;
 
 	@Inject
-	QuitController(@QuitWindow Stage window, QuitResponse response, ObservableList<Vault> vaults, ExecutorService executorService, VaultService vaultService) {
+	QuitController(@QuitWindow Stage window, ObservableList<Vault> vaults, ExecutorService executorService, VaultService vaultService, AtomicReference<QuitResponse> quitResponse) {
 		this.window = window;
-		this.response = response;
 		this.unlockedVaults = vaults.filtered(Vault::isUnlocked);
 		this.executorService = executorService;
 		this.vaultService = vaultService;
+		this.quitResponse = quitResponse;
+		window.setOnCloseRequest(windowEvent -> cancel());
 	}
 
 	@FXML
 	public void cancel() {
 		LOG.info("Quitting application canceled by user.");
 		window.close();
-		response.cancelQuit();
+		quitResponse.get().cancelQuit();
+		quitResponse.set(null);
 	}
 
 	@FXML
@@ -56,16 +59,16 @@ public class QuitController implements FxController {
 			LOG.info("Locked {}", lockAllTask.getValue().stream().map(Vault::getDisplayName).collect(Collectors.joining(", ")));
 			if (unlockedVaults.isEmpty()) {
 				window.close();
-				response.performQuit();
+				quitResponse.getAndSet(null).performQuit();
 			}
 		});
 		lockAllTask.setOnFailed(evt -> {
 			LOG.warn("Locking failed", lockAllTask.getException());
 			lockAndQuitButton.setDisable(false);
 			lockAndQuitButton.setContentDisplay(ContentDisplay.TEXT_ONLY);
-			// TODO: show force lock or force quit scene (and DO NOT cancelQuit() here!)
-			// see https://github.com/cryptomator/cryptomator/blob/1.4.16/main/ui/src/main/java/org/cryptomator/ui/model/Vault.java#L151-L163
-			response.cancelQuit();
+			// TODO: show force lock or force quit scene (and DO NOT cancelQuit() here!) (see https://github.com/cryptomator/cryptomator/pull/1416)
+			window.close();
+			quitResponse.getAndSet(null).cancelQuit();
 		});
 		executorService.execute(lockAllTask);
 	}

+ 8 - 0
main/ui/src/main/java/org/cryptomator/ui/quit/QuitModule.java

@@ -13,6 +13,8 @@ import org.cryptomator.ui.common.FxmlScene;
 import org.cryptomator.ui.common.StageFactory;
 
 import javax.inject.Provider;
+import javafx.beans.property.ObjectProperty;
+import javafx.beans.property.SimpleObjectProperty;
 import javafx.scene.Scene;
 import javafx.stage.Modality;
 import javafx.stage.Stage;
@@ -22,6 +24,12 @@ import java.util.ResourceBundle;
 @Module
 abstract class QuitModule {
 
+	@Provides
+	@QuitScoped
+	static ObjectProperty<Stage> provideStageProperty() {
+		return new SimpleObjectProperty<>();
+	}
+
 	@Provides
 	@QuitWindow
 	@QuitScoped