From e148e39fef3571171862fb28059709d6cc5cba5f Mon Sep 17 00:00:00 2001 From: En-Jan Chou Date: Mon, 13 Jan 2020 03:25:19 -0500 Subject: [PATCH] Rollback TrayMenuController to FxApplication code moving --- .../cryptomator/ui/fxapp/FxApplication.java | 97 +------------------ .../mainwindow/MainWindowTitleController.java | 28 +++++- .../ui/traymenu/TrayMenuController.java | 91 ++++++++++++++++- 3 files changed, 113 insertions(+), 103 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 acacd93c6..aca5650ea 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 @@ -3,21 +3,16 @@ package org.cryptomator.ui.fxapp; import dagger.Lazy; import javafx.application.Application; import javafx.application.Platform; -import javafx.beans.Observable; import javafx.beans.binding.Bindings; import javafx.beans.binding.BooleanBinding; import javafx.beans.value.ObservableValue; import javafx.collections.FXCollections; -import javafx.collections.ObservableList; import javafx.collections.ObservableSet; import javafx.stage.Stage; import org.cryptomator.common.LicenseHolder; -import org.cryptomator.common.ShutdownHook; import org.cryptomator.common.settings.Settings; import org.cryptomator.common.settings.UiTheme; import org.cryptomator.common.vaults.Vault; -import org.cryptomator.common.vaults.VaultState; -import org.cryptomator.common.vaults.Volume; import org.cryptomator.jni.JniException; import org.cryptomator.jni.MacApplicationUiAppearance; import org.cryptomator.jni.MacApplicationUiState; @@ -32,21 +27,13 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.inject.Inject; -import javax.inject.Named; -import java.awt.Desktop; import java.awt.desktop.QuitResponse; -import java.util.EnumSet; -import java.util.EventObject; import java.util.Optional; -import java.util.Set; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.atomic.AtomicBoolean; @FxApplicationScoped public class FxApplication extends Application { private static final Logger LOG = LoggerFactory.getLogger(FxApplication.class); - private static final Set STATES_ALLOWING_TERMINATION = EnumSet.of(VaultState.LOCKED, VaultState.NEEDS_MIGRATION, VaultState.MISSING, VaultState.ERROR); private final Settings settings; private final Lazy mainWindow; @@ -58,13 +45,9 @@ public class FxApplication extends Application { private final LicenseHolder licenseHolder; private final ObservableSet visibleStages = FXCollections.observableSet(); private final BooleanBinding hasVisibleStages = Bindings.isNotEmpty(visibleStages); - private final AtomicBoolean allowSuddenTermination; - private final CountDownLatch shutdownLatch; - private final ShutdownHook shutdownHook; - private final ObservableList vaults; @Inject - FxApplication(Settings settings, Lazy mainWindow, Lazy preferencesWindow, UnlockComponent.Builder unlockWindowBuilder, QuitComponent.Builder quitWindowBuilder, Optional macFunctions, VaultService vaultService, LicenseHolder licenseHolder, ObservableList vaults, @Named("shutdownLatch") CountDownLatch shutdownLatch, ShutdownHook shutdownHook) { + FxApplication(Settings settings, Lazy mainWindow, Lazy preferencesWindow, UnlockComponent.Builder unlockWindowBuilder, QuitComponent.Builder quitWindowBuilder, Optional macFunctions, VaultService vaultService, LicenseHolder licenseHolder) { this.settings = settings; this.mainWindow = mainWindow; this.preferencesWindow = preferencesWindow; @@ -73,10 +56,6 @@ public class FxApplication extends Application { this.macFunctions = macFunctions; this.vaultService = vaultService; this.licenseHolder = licenseHolder; - this.vaults = vaults; - this.shutdownLatch = shutdownLatch; - this.shutdownHook = shutdownHook; - this.allowSuddenTermination = new AtomicBoolean(true); } public void start() { @@ -87,25 +66,6 @@ public class FxApplication extends Application { settings.theme().addListener(this::themeChanged); loadSelectedStyleSheet(settings.theme().get()); - - vaults.addListener(this::vaultsChanged); - - shutdownHook.runOnShutdown(this::forceUnmountRemainingVaults); - - // register preferences shortcut - if (Desktop.getDesktop().isSupported(Desktop.Action.APP_PREFERENCES)) { - Desktop.getDesktop().setPreferencesHandler(this::showPreferencesWindow); - } - - // register quit handler - if (Desktop.getDesktop().isSupported(Desktop.Action.APP_QUIT_HANDLER)) { - Desktop.getDesktop().setQuitHandler(this::handleQuitRequest); - } - - // allow sudden termination - if (Desktop.getDesktop().isSupported(Desktop.Action.APP_SUDDEN_TERMINATION)) { - Desktop.getDesktop().enableSuddenTermination(); - } } @Override @@ -126,7 +86,7 @@ public class FxApplication extends Application { } } - public void showPreferencesTab(SelectedPreferencesTab selectedTab) { + public void showPreferencesWindow(SelectedPreferencesTab selectedTab) { Platform.runLater(() -> { Stage stage = preferencesWindow.get().showPreferencesWindow(selectedTab); addVisibleStage(stage); @@ -150,7 +110,7 @@ public class FxApplication extends Application { }); } - private void showQuitWindow(@SuppressWarnings("unused") EventObject actionEvent, QuitResponse response) { + public void showQuitWindow(QuitResponse response) { Platform.runLater(() -> { Stage stage = quitWindowBuilder.quitResponse(response).build().showQuitWindow(); addVisibleStage(stage); @@ -185,55 +145,4 @@ public class FxApplication extends Application { } } - public void quitApplication() { - handleQuitRequest(null, new QuitResponse() { - @Override - public void performQuit() { - shutdownLatch.countDown(); - } - - @Override - public void cancelQuit() { - // no-op - } - }); - } - - private void showPreferencesWindow(@SuppressWarnings("unused") EventObject actionEvent) { - showPreferencesTab(SelectedPreferencesTab.ANY); - } - - private void handleQuitRequest(EventObject e, QuitResponse response) { - if (allowSuddenTermination.get()) { - response.performQuit(); // really? - } else { - showQuitWindow(e, response); - } - } - - private void vaultsChanged(@SuppressWarnings("unused") Observable observable) { - boolean allVaultsAllowTermination = vaults.stream().map(Vault::getState).allMatch(STATES_ALLOWING_TERMINATION::contains); - boolean suddenTerminationChanged = allowSuddenTermination.compareAndSet(!allVaultsAllowTermination, allVaultsAllowTermination); - if (suddenTerminationChanged && Desktop.getDesktop().isSupported(Desktop.Action.APP_SUDDEN_TERMINATION)) { - if (allVaultsAllowTermination) { - Desktop.getDesktop().enableSuddenTermination(); - LOG.debug("sudden termination enabled"); - } else { - Desktop.getDesktop().disableSuddenTermination(); - LOG.debug("sudden termination disabled"); - } - } - } - - private void forceUnmountRemainingVaults() { - for (Vault vault : vaults) { - if (vault.isUnlocked()) { - try { - vault.lock(true); - } catch (Volume.VolumeException e) { - LOG.error("Failed to unmount vault " + vault.getPath(), e); - } - } - } - } } diff --git a/main/ui/src/main/java/org/cryptomator/ui/mainwindow/MainWindowTitleController.java b/main/ui/src/main/java/org/cryptomator/ui/mainwindow/MainWindowTitleController.java index ed1d51c50..009a0a6af 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/mainwindow/MainWindowTitleController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/mainwindow/MainWindowTitleController.java @@ -5,15 +5,19 @@ import javafx.fxml.FXML; import javafx.scene.layout.HBox; import javafx.stage.Stage; import org.cryptomator.common.LicenseHolder; +import org.cryptomator.common.vaults.VaultListManager; import org.cryptomator.ui.common.FxController; import org.cryptomator.ui.fxapp.FxApplication; import org.cryptomator.ui.fxapp.UpdateChecker; import org.cryptomator.ui.preferences.SelectedPreferencesTab; +import org.cryptomator.ui.wrongfilealert.WrongFileAlertComponent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.inject.Inject; import javax.inject.Named; +import java.awt.desktop.QuitResponse; +import java.util.concurrent.CountDownLatch; @MainWindowScoped public class MainWindowTitleController implements FxController { @@ -24,6 +28,7 @@ public class MainWindowTitleController implements FxController { private final Stage window; private final FxApplication application; + private final CountDownLatch shutdownLatch; private final boolean minimizeToSysTray; private final UpdateChecker updateChecker; private final BooleanBinding updateAvailable; @@ -33,9 +38,10 @@ public class MainWindowTitleController implements FxController { private double yOffset; @Inject - MainWindowTitleController(@MainWindow Stage window, FxApplication application, @Named("trayMenuSupported") boolean minimizeToSysTray, UpdateChecker updateChecker, LicenseHolder licenseHolder) { + MainWindowTitleController(@MainWindow Stage window, FxApplication application, @Named("shutdownLatch") CountDownLatch shutdownLatch, @Named("trayMenuSupported") boolean minimizeToSysTray, UpdateChecker updateChecker, LicenseHolder licenseHolder) { this.window = window; this.application = application; + this.shutdownLatch = shutdownLatch; this.minimizeToSysTray = minimizeToSysTray; this.updateChecker = updateChecker; this.updateAvailable = updateChecker.latestVersionProperty().isNotNull(); @@ -61,10 +67,24 @@ public class MainWindowTitleController implements FxController { if (minimizeToSysTray) { window.close(); } else { - application.quitApplication(); + quitApplication(); } } + private void quitApplication() { + application.showQuitWindow(new QuitResponse() { + @Override + public void performQuit() { + shutdownLatch.countDown(); + } + + @Override + public void cancelQuit() { + // no-op + } + }); + } + @FXML public void minimize() { window.setIconified(true); @@ -72,12 +92,12 @@ public class MainWindowTitleController implements FxController { @FXML public void showPreferences() { - application.showPreferencesTab(SelectedPreferencesTab.ANY); + application.showPreferencesWindow(SelectedPreferencesTab.ANY); } @FXML public void showDonationKeyPreferences() { - application.showPreferencesTab(SelectedPreferencesTab.DONATION_KEY); + application.showPreferencesWindow(SelectedPreferencesTab.DONATION_KEY); } /* Getter/Setter */ 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 5220fd5c9..bef3c441c 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 @@ -3,33 +3,57 @@ package org.cryptomator.ui.traymenu; import javafx.application.Platform; import javafx.beans.Observable; import javafx.collections.ObservableList; +import org.cryptomator.common.ShutdownHook; +import org.cryptomator.common.settings.Settings; import org.cryptomator.common.vaults.Vault; +import org.cryptomator.common.vaults.VaultState; +import org.cryptomator.common.vaults.Volume; +import org.cryptomator.ui.fxapp.FxApplication; import org.cryptomator.ui.launcher.FxApplicationStarter; import org.cryptomator.ui.preferences.SelectedPreferencesTab; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; 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.desktop.QuitResponse; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.util.EnumSet; import java.util.EventObject; import java.util.ResourceBundle; +import java.util.Set; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Consumer; @TrayMenuScoped class TrayMenuController { + + private static final Logger LOG = LoggerFactory.getLogger(TrayMenuController.class); + public static final Set STATES_ALLOWING_TERMINATION = EnumSet.of(VaultState.LOCKED, VaultState.NEEDS_MIGRATION, VaultState.MISSING, VaultState.ERROR); + private final ResourceBundle resourceBundle; private final FxApplicationStarter fxApplicationStarter; + private final CountDownLatch shutdownLatch; + private final ShutdownHook shutdownHook; private final ObservableList vaults; private final PopupMenu menu; + private final AtomicBoolean allowSuddenTermination; @Inject - TrayMenuController(ResourceBundle resourceBundle, FxApplicationStarter fxApplicationStarter, ObservableList vaults) { + TrayMenuController(ResourceBundle resourceBundle, FxApplicationStarter fxApplicationStarter, @Named("shutdownLatch") CountDownLatch shutdownLatch, ShutdownHook shutdownHook, ObservableList vaults) { this.resourceBundle = resourceBundle; this.fxApplicationStarter = fxApplicationStarter; + this.shutdownLatch = shutdownLatch; + this.shutdownHook = shutdownHook; this.vaults = vaults; this.menu = new PopupMenu(); + this.allowSuddenTermination = new AtomicBoolean(true); } public PopupMenu getMenu() { @@ -40,11 +64,38 @@ class TrayMenuController { vaults.addListener(this::vaultListChanged); rebuildMenu(); + + // register preferences shortcut + if (Desktop.getDesktop().isSupported(Desktop.Action.APP_PREFERENCES)) { + Desktop.getDesktop().setPreferencesHandler(this::showPreferencesWindow); + } + + // register quit handler + if (Desktop.getDesktop().isSupported(Desktop.Action.APP_QUIT_HANDLER)) { + Desktop.getDesktop().setQuitHandler(this::handleQuitRequest); + } + shutdownHook.runOnShutdown(this::forceUnmountRemainingVaults); + + // allow sudden termination + if (Desktop.getDesktop().isSupported(Desktop.Action.APP_SUDDEN_TERMINATION)) { + Desktop.getDesktop().enableSuddenTermination(); + } } private void vaultListChanged(@SuppressWarnings("unused") Observable observable) { assert Platform.isFxApplicationThread(); rebuildMenu(); + boolean allVaultsAllowTermination = vaults.stream().map(Vault::getState).allMatch(STATES_ALLOWING_TERMINATION::contains); + boolean suddenTerminationChanged = allowSuddenTermination.compareAndSet(!allVaultsAllowTermination, allVaultsAllowTermination); + if (suddenTerminationChanged && Desktop.getDesktop().isSupported(Desktop.Action.APP_SUDDEN_TERMINATION)) { + if (allVaultsAllowTermination) { + Desktop.getDesktop().enableSuddenTermination(); + LOG.debug("sudden termination enabled"); + } else { + Desktop.getDesktop().disableSuddenTermination(); + LOG.debug("sudden termination disabled"); + } + } } private void rebuildMenu() { @@ -115,15 +166,45 @@ class TrayMenuController { fxApplicationStarter.get(true).thenAccept(app -> app.getVaultService().reveal(vault)); } - public void showMainWindow(@SuppressWarnings("unused") ActionEvent actionEvent) { + void showMainWindow(@SuppressWarnings("unused") ActionEvent actionEvent) { fxApplicationStarter.get(true).thenAccept(app -> app.showMainWindow()); } private void showPreferencesWindow(@SuppressWarnings("unused") EventObject actionEvent) { - fxApplicationStarter.get(true).thenAccept(app -> app.showPreferencesTab(SelectedPreferencesTab.ANY)); + fxApplicationStarter.get(true).thenAccept(app -> app.showPreferencesWindow(SelectedPreferencesTab.ANY)); } - private void quitApplication(@SuppressWarnings("unused") EventObject actionEvent) { - fxApplicationStarter.get(true).thenAccept(app -> app.quitApplication()); + private void handleQuitRequest(EventObject e, QuitResponse response) { + if (allowSuddenTermination.get()) { + response.performQuit(); // really? + } else { + fxApplicationStarter.get(true).thenAccept(app -> app.showQuitWindow(response)); + } + } + + private void quitApplication(EventObject actionEvent) { + handleQuitRequest(actionEvent, new QuitResponse() { + @Override + public void performQuit() { + shutdownLatch.countDown(); + } + + @Override + public void cancelQuit() { + // no-op + } + }); + } + + private void forceUnmountRemainingVaults() { + for (Vault vault : vaults) { + if (vault.isUnlocked()) { + try { + vault.lock(true); + } catch (Volume.VolumeException e) { + LOG.error("Failed to unmount vault " + vault.getPath(), e); + } + } + } } }