mirror of
https://github.com/cryptomator/cryptomator.git
synced 2026-04-20 09:36:55 -04:00
hooked up in UI
This commit is contained in:
@@ -4,10 +4,15 @@ import org.cryptomator.common.Environment;
|
||||
import org.cryptomator.common.settings.Settings;
|
||||
import org.cryptomator.ui.common.FxController;
|
||||
import org.cryptomator.ui.fxapp.UpdateChecker;
|
||||
import org.cryptomator.updater.UpdateMechanism;
|
||||
import org.cryptomator.updater.UpdateProcess;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javafx.animation.PauseTransition;
|
||||
import javafx.application.Application;
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.binding.Bindings;
|
||||
import javafx.beans.binding.BooleanBinding;
|
||||
import javafx.beans.binding.ObjectBinding;
|
||||
@@ -16,9 +21,11 @@ import javafx.beans.property.BooleanProperty;
|
||||
import javafx.beans.property.ReadOnlyStringProperty;
|
||||
import javafx.beans.property.SimpleBooleanProperty;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
import javafx.concurrent.Task;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.control.CheckBox;
|
||||
import javafx.scene.control.ContentDisplay;
|
||||
import java.io.IOException;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.Duration;
|
||||
@@ -29,11 +36,14 @@ import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.FormatStyle;
|
||||
import java.util.Locale;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
|
||||
@PreferencesScoped
|
||||
public class UpdatesPreferencesController implements FxController {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(UpdatesPreferencesController.class);
|
||||
private static final String DOWNLOADS_URI_TEMPLATE = "https://cryptomator.org/downloads/" //
|
||||
+ "?utm_source=cryptomator-desktop" //
|
||||
+ "&utm_medium=update-notification&" //
|
||||
@@ -56,6 +66,9 @@ public class UpdatesPreferencesController implements FxController {
|
||||
private final DateTimeFormatter formatter;
|
||||
private final BooleanBinding upToDate;
|
||||
private final String downloadsUri;
|
||||
private final UpdateMechanism updateMechanism;
|
||||
public final Task<UpdateProcess> updatePreparationTask;
|
||||
private final StringBinding updateButtonTitle;
|
||||
|
||||
/* FXML */
|
||||
public CheckBox checkForUpdatesCheckbox;
|
||||
@@ -78,6 +91,18 @@ public class UpdatesPreferencesController implements FxController {
|
||||
this.checkFailed = updateChecker.checkFailedProperty();
|
||||
this.lastUpdateCheckMessage = Bindings.createStringBinding(this::getLastUpdateCheckMessage, lastSuccessfulUpdateCheck);
|
||||
this.downloadsUri = DOWNLOADS_URI_TEMPLATE.formatted(URLEncoder.encode(currentVersion, StandardCharsets.US_ASCII));
|
||||
this.updateMechanism = UpdateMechanism.get();
|
||||
this.updatePreparationTask = new Task<>() { // TODO custom class?
|
||||
@Override
|
||||
protected UpdateProcess call() throws IOException, InterruptedException {
|
||||
var updateProcess = updateMechanism.prepareUpdate();
|
||||
do {
|
||||
updateProgress(updateProcess.preparationProgress(), 1.0);
|
||||
} while (!updateProcess.await(100, TimeUnit.MILLISECONDS));
|
||||
return updateProcess;
|
||||
}
|
||||
};
|
||||
this.updateButtonTitle = Bindings.createStringBinding(this::getUpdateButtonTitle, updatePreparationTask.stateProperty());
|
||||
}
|
||||
|
||||
public void initialize() {
|
||||
@@ -108,6 +133,26 @@ public class UpdatesPreferencesController implements FxController {
|
||||
environment.getLogDir().ifPresent(logDirPath -> application.getHostServices().showDocument(logDirPath.toUri().toString()));
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void prepareUpdate() {
|
||||
if (updatePreparationTask.isDone()) {
|
||||
try {
|
||||
// TODO: check if all vaults closed?
|
||||
var restartProcess = updatePreparationTask.get().applyUpdate();
|
||||
assert restartProcess.isAlive();
|
||||
Platform.exit(); // TODO: prompt?
|
||||
} catch (IOException | InterruptedException | ExecutionException e) {
|
||||
LOG.error("Oh no", e); // TODO: Show error dialog
|
||||
}
|
||||
} else if (updatePreparationTask.isRunning()) {
|
||||
throw new IllegalStateException("Update already in progress");
|
||||
} else if (updatePreparationTask.isCancelled()) {
|
||||
throw new IllegalStateException("Update preparation task was cancelled");
|
||||
} else {
|
||||
Thread.startVirtualThread(updatePreparationTask);
|
||||
}
|
||||
}
|
||||
|
||||
/* Observable Properties */
|
||||
|
||||
public ObjectBinding<ContentDisplay> checkForUpdatesButtonStateProperty() {
|
||||
@@ -186,4 +231,21 @@ public class UpdatesPreferencesController implements FxController {
|
||||
return checkFailed.getValue();
|
||||
}
|
||||
|
||||
public Task<UpdateProcess> getUpdatePreparationTask() {
|
||||
return updatePreparationTask;
|
||||
}
|
||||
|
||||
public StringBinding updateButtonTitleProperty() {
|
||||
return updateButtonTitle;
|
||||
}
|
||||
|
||||
public String getUpdateButtonTitle() {
|
||||
return switch (updatePreparationTask.getState()) {
|
||||
case READY -> "Prepare Update"; // TODO: resourceBundle.getString("preferences.updates.preparingUpdate")...
|
||||
case SCHEDULED, RUNNING -> "Preparing Update...";
|
||||
case SUCCEEDED -> "Restart to Update";
|
||||
case FAILED, CANCELLED -> "failed";
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,17 +1,15 @@
|
||||
package org.cryptomator.updater;
|
||||
|
||||
import org.cryptomator.integrations.common.IntegrationsLoader;
|
||||
import org.cryptomator.integrations.common.NamedServiceProvider;
|
||||
import org.jetbrains.annotations.Blocking;
|
||||
|
||||
import javafx.concurrent.Task;
|
||||
import java.io.IOException;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public interface UpdateMechanism extends NamedServiceProvider {
|
||||
|
||||
static Stream<UpdateMechanism> get() {
|
||||
return IntegrationsLoader.loadAll(UpdateMechanism.class);
|
||||
static UpdateMechanism get() {
|
||||
return new MacOsDmgUpdateMechanism(); // TODO: IntegrationsLoader.load(UpdateMechanism.class).orElseThrow();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -23,7 +21,7 @@ public interface UpdateMechanism extends NamedServiceProvider {
|
||||
|
||||
/**
|
||||
* Performs as much as possible to prepare the update. This may include downloading the update, checking signatures, etc.
|
||||
* @return a {@link Task} that can be used to monitor the progress of the update preparation. The task will complete when the preparation is done.
|
||||
* @return a new {@link Task} that can be used to monitor the progress of the update preparation. The task will complete when the preparation is done.
|
||||
* @throws IOException I/O error during preparation, such as network issues or file access problems.
|
||||
*/
|
||||
UpdateProcess prepareUpdate() throws IOException; // TODO: exception types?
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
<?import javafx.scene.control.Tooltip?>
|
||||
<?import javafx.scene.text.TextFlow?>
|
||||
<?import javafx.scene.text.Text?>
|
||||
<?import javafx.scene.control.ProgressBar?>
|
||||
<VBox xmlns:fx="http://javafx.com/fxml"
|
||||
xmlns="http://javafx.com/javafx"
|
||||
fx:controller="org.cryptomator.ui.preferences.UpdatesPreferencesController"
|
||||
@@ -53,5 +54,12 @@
|
||||
</graphic>
|
||||
</Label>
|
||||
<Hyperlink text="${linkLabel.value}" onAction="#visitDownloadsPage" textAlignment="CENTER" wrapText="true" styleClass="hyperlink-underline" visible="${controller.updateAvailable}" managed="${controller.updateAvailable}"/>
|
||||
|
||||
<Button text="${controller.updateButtonTitle}" onAction="#prepareUpdate" disable="${controller.updatePreparationTask.running}">
|
||||
<graphic>
|
||||
<FontAwesome5IconView glyphSize="12" styleClass="glyph-icon-primary" glyph="FILE_DOWNLOAD"/>
|
||||
</graphic>
|
||||
</Button>
|
||||
<ProgressBar progress="${controller.updatePreparationTask.progress}" visible="${controller.updatePreparationTask.running}"/>
|
||||
</VBox>
|
||||
</VBox>
|
||||
|
||||
Reference in New Issue
Block a user