Преглед изворни кода

Determine autostart state async (#418)

Sebastian Stenzel пре 5 година
родитељ
комит
d37e0dd5e1

+ 11 - 7
main/ui/src/main/java/org/cryptomator/ui/preferences/AutoStartMacStrategy.java

@@ -4,10 +4,13 @@ import org.cryptomator.jni.MacFunctions;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionStage;
+
 class AutoStartMacStrategy implements AutoStartStrategy {
 
 	private static final Logger LOG = LoggerFactory.getLogger(AutoStartMacStrategy.class);
-	
+
 	private final MacFunctions macFunctions;
 
 	public AutoStartMacStrategy(MacFunctions macFunctions) {
@@ -15,25 +18,26 @@ class AutoStartMacStrategy implements AutoStartStrategy {
 	}
 
 	@Override
-	public boolean isAutoStartEnabled() {
-		return macFunctions.launchServices().isLoginItemEnabled();
+	public CompletionStage<Boolean> isAutoStartEnabled() {
+		boolean enabled = macFunctions.launchServices().isLoginItemEnabled();
+		return CompletableFuture.completedFuture(enabled);
 	}
 
 	@Override
-	public void enableAutoStart() {
+	public void enableAutoStart() throws TogglingAutoStartFailedException {
 		if (macFunctions.launchServices().enableLoginItem()) {
 			LOG.debug("Added login item.");
 		} else {
-			LOG.warn("Adding login item failed.");
+			throw new TogglingAutoStartFailedException("Failed to add login item.");
 		}
 	}
 
 	@Override
-	public void disableAutoStart() {
+	public void disableAutoStart() throws TogglingAutoStartFailedException {
 		if (macFunctions.launchServices().disableLoginItem()) {
 			LOG.debug("Removed login item.");
 		} else {
-			LOG.warn("Removing login item failed.");
+			throw new TogglingAutoStartFailedException("Failed to remove login item.");
 		}
 	}
 }

+ 17 - 3
main/ui/src/main/java/org/cryptomator/ui/preferences/AutoStartStrategy.java

@@ -1,10 +1,24 @@
 package org.cryptomator.ui.preferences;
 
+import java.util.concurrent.CompletionStage;
+
 public interface AutoStartStrategy {
 
-	boolean isAutoStartEnabled();
+	CompletionStage<Boolean> isAutoStartEnabled();
+
+	void enableAutoStart() throws TogglingAutoStartFailedException;
+
+	void disableAutoStart() throws TogglingAutoStartFailedException;
+
+	class TogglingAutoStartFailedException extends Exception {
 
-	void enableAutoStart();
+		public TogglingAutoStartFailedException(String message) {
+			super(message);
+		}
 
-	void disableAutoStart();
+		public TogglingAutoStartFailedException(String message, Throwable cause) {
+			super(message, cause);
+		}
+		
+	}
 }

+ 42 - 17
main/ui/src/main/java/org/cryptomator/ui/preferences/GeneralPreferencesController.java

@@ -1,6 +1,8 @@
 package org.cryptomator.ui.preferences;
 
+import javafx.application.Platform;
 import javafx.beans.value.ObservableValue;
+import javafx.concurrent.Task;
 import javafx.fxml.FXML;
 import javafx.geometry.NodeOrientation;
 import javafx.scene.control.CheckBox;
@@ -18,6 +20,7 @@ import org.slf4j.LoggerFactory;
 import javax.inject.Inject;
 import javax.inject.Named;
 import java.util.Optional;
+import java.util.concurrent.ExecutorService;
 
 @PreferencesScoped
 public class GeneralPreferencesController implements FxController {
@@ -27,6 +30,7 @@ public class GeneralPreferencesController implements FxController {
 	private final Settings settings;
 	private final boolean trayMenuSupported;
 	private final Optional<AutoStartStrategy> autoStartStrategy;
+	private final ExecutorService executor;
 	public ChoiceBox<UiTheme> themeChoiceBox;
 	public CheckBox startHiddenCheckbox;
 	public CheckBox debugModeCheckbox;
@@ -36,10 +40,11 @@ public class GeneralPreferencesController implements FxController {
 	public RadioButton nodeOrientationRtl;
 
 	@Inject
-	GeneralPreferencesController(Settings settings, @Named("trayMenuSupported") boolean trayMenuSupported, Optional<AutoStartStrategy> autoStartStrategy) {
+	GeneralPreferencesController(Settings settings, @Named("trayMenuSupported") boolean trayMenuSupported, Optional<AutoStartStrategy> autoStartStrategy, ExecutorService executor) {
 		this.settings = settings;
 		this.trayMenuSupported = trayMenuSupported;
 		this.autoStartStrategy = autoStartStrategy;
+		this.executor = executor;
 	}
 
 	@FXML
@@ -52,8 +57,11 @@ public class GeneralPreferencesController implements FxController {
 
 		debugModeCheckbox.selectedProperty().bindBidirectional(settings.debugMode());
 
-		autoStartCheckbox.setSelected(this.isAutoStartEnabled());
-		autoStartCheckbox.selectedProperty().addListener(this::toggleAutoStart);
+		autoStartStrategy.ifPresent(autoStart -> {
+			autoStart.isAutoStartEnabled().thenAccept(enabled -> {
+				Platform.runLater(() -> autoStartCheckbox.setSelected(enabled));
+			});
+		});
 
 		nodeOrientationLtr.setSelected(settings.userInterfaceOrientation().get() == NodeOrientation.LEFT_TO_RIGHT);
 		nodeOrientationRtl.setSelected(settings.userInterfaceOrientation().get() == NodeOrientation.RIGHT_TO_LEFT);
@@ -68,20 +76,6 @@ public class GeneralPreferencesController implements FxController {
 		return autoStartStrategy.isPresent();
 	}
 
-	private boolean isAutoStartEnabled() {
-		return autoStartStrategy.map(AutoStartStrategy::isAutoStartEnabled).orElse(false);
-	}
-
-	private void toggleAutoStart(@SuppressWarnings("unused") ObservableValue<? extends Boolean> observable, @SuppressWarnings("unused") boolean oldValue, boolean newValue) {
-		autoStartStrategy.ifPresent(autoStart -> {
-			if (newValue) {
-				autoStart.enableAutoStart();
-			} else {
-				autoStart.disableAutoStart();
-			}
-		});
-	}
-
 	private void toggleNodeOrientation(@SuppressWarnings("unused") ObservableValue<? extends Toggle> observable, @SuppressWarnings("unused") Toggle oldValue, Toggle newValue) {
 		if (nodeOrientationLtr.equals(newValue)) {
 			settings.userInterfaceOrientation().set(NodeOrientation.LEFT_TO_RIGHT);
@@ -92,6 +86,16 @@ public class GeneralPreferencesController implements FxController {
 		}
 	}
 
+	@FXML
+	public void toggleAutoStart() {
+		autoStartStrategy.ifPresent(autoStart -> {
+			boolean enableAutoStart = autoStartCheckbox.isSelected();
+			Task<Void> toggleTask = new ToggleAutoStartTask(autoStart, enableAutoStart);
+			toggleTask.setOnFailed(evt -> autoStartCheckbox.setSelected(!enableAutoStart)); // restore previous state
+			executor.execute(toggleTask);
+		});
+	}
+
 	/* Helper classes */
 
 	private static class UiThemeConverter extends StringConverter<UiTheme> {
@@ -107,4 +111,25 @@ public class GeneralPreferencesController implements FxController {
 		}
 	}
 
+	private static class ToggleAutoStartTask extends Task<Void> {
+
+		private final AutoStartStrategy autoStart;
+		private final boolean enable;
+
+		public ToggleAutoStartTask(AutoStartStrategy autoStart, boolean enable) {
+			this.autoStart = autoStart;
+			this.enable = enable;
+		}
+
+		@Override
+		protected Void call() throws Exception {
+			if (enable) {
+				autoStart.enableAutoStart();
+			} else {
+				autoStart.disableAutoStart();
+			}
+			return null;
+		}
+	}
+
 }

+ 1 - 1
main/ui/src/main/resources/fxml/preferences_general.fxml

@@ -34,6 +34,6 @@
 
 		<CheckBox fx:id="debugModeCheckbox" text="%preferences.general.debugLogging"/>
 
-		<CheckBox fx:id="autoStartCheckbox" text="%preferences.general.autoStart" visible="${controller.autoStartSupported}" managed="${controller.autoStartSupported}"/>
+		<CheckBox fx:id="autoStartCheckbox" text="%preferences.general.autoStart" visible="${controller.autoStartSupported}" managed="${controller.autoStartSupported}" onAction="#toggleAutoStart"/>
 	</children>
 </VBox>