From 43d0dd99eca4e9f8ddf0582a365565b7fe5ae6cd Mon Sep 17 00:00:00 2001 From: Jan-Peter Klein Date: Thu, 4 Apr 2024 12:37:56 +0200 Subject: [PATCH] adjusted code as per PR suggestions --- .../cryptomator/common/settings/Settings.java | 18 +++++ .../cryptomator/ui/fxapp/UpdateChecker.java | 41 +++++------ .../mainwindow/MainWindowTitleController.java | 2 +- .../UpdatesPreferencesController.java | 68 ++++++++++--------- .../UpdateReminderComponent.java | 24 +++++-- .../resources/fxml/preferences_updates.fxml | 8 +-- src/main/resources/i18n/strings.properties | 2 +- 7 files changed, 99 insertions(+), 64 deletions(-) diff --git a/src/main/java/org/cryptomator/common/settings/Settings.java b/src/main/java/org/cryptomator/common/settings/Settings.java index 6c46654c1..019f87b2a 100644 --- a/src/main/java/org/cryptomator/common/settings/Settings.java +++ b/src/main/java/org/cryptomator/common/settings/Settings.java @@ -25,6 +25,10 @@ import javafx.beans.property.StringProperty; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.geometry.NodeOrientation; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; import java.util.function.Consumer; public class Settings { @@ -163,6 +167,20 @@ public class Settings { } }); } + + var dateTimeString = !lastUpdateCheck.get().isEmpty() ? lastUpdateCheck.get() : DEFAULT_LAST_UPDATE_CHECK; + try { + LocalDateTime dateTime = LocalDateTime.parse(dateTimeString, DateTimeFormatter.ISO_DATE_TIME); + lastUpdateCheck.set(dateTime.toString()); + } catch (DateTimeParseException e) { + try { + LocalDate date = LocalDate.parse(dateTimeString, DateTimeFormatter.ISO_DATE); + lastUpdateCheck.set(LocalDateTime.of(date, LocalDate.MIN.atStartOfDay().toLocalTime()).toString()); + } catch (DateTimeParseException ex) { + LOG.error("The date/time format is invalid:" + dateTimeString, ex); + } + } + } SettingsJson serialized() { diff --git a/src/main/java/org/cryptomator/ui/fxapp/UpdateChecker.java b/src/main/java/org/cryptomator/ui/fxapp/UpdateChecker.java index 2cbf9bb31..a4af88b93 100644 --- a/src/main/java/org/cryptomator/ui/fxapp/UpdateChecker.java +++ b/src/main/java/org/cryptomator/ui/fxapp/UpdateChecker.java @@ -1,11 +1,13 @@ package org.cryptomator.ui.fxapp; import org.cryptomator.common.Environment; +import org.cryptomator.common.SemVerComparator; import org.cryptomator.common.settings.Settings; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.inject.Inject; +import javafx.beans.binding.Bindings; import javafx.beans.binding.BooleanBinding; import javafx.beans.property.ObjectProperty; import javafx.beans.property.ReadOnlyStringProperty; @@ -16,10 +18,8 @@ import javafx.concurrent.ScheduledService; import javafx.concurrent.Worker; import javafx.concurrent.WorkerStateEvent; import javafx.util.Duration; -import java.time.LocalDate; import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeParseException; +import java.util.Comparator; @FxApplicationScoped public class UpdateChecker { @@ -33,6 +33,8 @@ public class UpdateChecker { private final ScheduledService updateCheckerService; private final ObjectProperty state = new SimpleObjectProperty<>(UpdateCheckState.NOT_CHECKED); private final ObjectProperty updateCheckTimeProperty = new SimpleObjectProperty<>(); + private final Comparator versionComparator = new SemVerComparator(); + private final BooleanBinding updateAvailable; @Inject UpdateChecker(Settings settings, // @@ -42,20 +44,14 @@ public class UpdateChecker { this.settings = settings; this.updateCheckerService = updateCheckerService; this.latestVersionProperty.set(settings.latestVersion.get()); - var dateTimeString = !settings.lastUpdateCheck.get().isEmpty() ? settings.lastUpdateCheck.get() : Settings.DEFAULT_LAST_UPDATE_CHECK; - try { - LocalDateTime dateTime = LocalDateTime.parse(dateTimeString, DateTimeFormatter.ISO_DATE_TIME); - this.updateCheckTimeProperty.set(dateTime); - } catch (DateTimeParseException e) { - try { - LocalDate date = LocalDate.parse(dateTimeString, DateTimeFormatter.ISO_DATE); - this.updateCheckTimeProperty.set(LocalDateTime.of(date, LocalDate.MIN.atStartOfDay().toLocalTime())); - } catch (DateTimeParseException ex) { - LOG.error("The date/time format is invalid:" + dateTimeString, ex); - } - } - this.latestVersionProperty().addListener((_, _, newValue) -> settings.latestVersion.set(newValue)); - this.updateCheckTimeProperty().addListener((_,_,newValue) -> settings.lastUpdateCheck.set(newValue.toString())); + this.updateCheckTimeProperty.set(LocalDateTime.parse(settings.lastUpdateCheck.get())); + this.updateAvailable = Bindings.createBooleanBinding(() -> { + var latestVersion = latestVersionProperty.get(); + return latestVersion != null && versionComparator.compare(getCurrentVersion(), latestVersion) < 0; + }, latestVersionProperty); + + this.latestVersionProperty.addListener((_, _, newValue) -> settings.latestVersion.set(newValue)); + this.updateCheckTimeProperty.addListener((_, _, newValue) -> settings.lastUpdateCheck.set(newValue.toString())); } public void automaticallyCheckForUpdatesIfEnabled() { @@ -112,8 +108,12 @@ public class UpdateChecker { return latestVersionProperty; } - public String getCurrentVersion() { - return env.getAppVersion(); + + public BooleanBinding updateAvailableProperty(){ + return updateAvailable; + } + public boolean isUpdateAvailable(){ + return updateAvailable.get(); } public ObjectProperty updateCheckTimeProperty() { @@ -124,4 +124,7 @@ public class UpdateChecker { return state; } + public String getCurrentVersion() { + return env.getAppVersion(); + } } diff --git a/src/main/java/org/cryptomator/ui/mainwindow/MainWindowTitleController.java b/src/main/java/org/cryptomator/ui/mainwindow/MainWindowTitleController.java index 2dcbd6095..f3c92790d 100644 --- a/src/main/java/org/cryptomator/ui/mainwindow/MainWindowTitleController.java +++ b/src/main/java/org/cryptomator/ui/mainwindow/MainWindowTitleController.java @@ -46,7 +46,7 @@ public class MainWindowTitleController implements FxController { this.appWindows = appWindows; this.trayMenuInitialized = trayMenu.isInitialized(); this.updateChecker = updateChecker; - this.updateAvailable = updateChecker.updateCheckStateProperty().isEqualTo(UpdateChecker.UpdateCheckState.CHECK_SUCCESSFUL).and(updateChecker.latestVersionProperty().isNotEqualTo(updateChecker.getCurrentVersion())); + this.updateAvailable = updateChecker.updateAvailableProperty(); this.licenseHolder = licenseHolder; this.settings = settings; this.showMinimizeButton = Bindings.createBooleanBinding(this::isShowMinimizeButton, settings.showMinimizeButton, settings.showTrayIcon); diff --git a/src/main/java/org/cryptomator/ui/preferences/UpdatesPreferencesController.java b/src/main/java/org/cryptomator/ui/preferences/UpdatesPreferencesController.java index 49f2a2250..4c1a0d315 100644 --- a/src/main/java/org/cryptomator/ui/preferences/UpdatesPreferencesController.java +++ b/src/main/java/org/cryptomator/ui/preferences/UpdatesPreferencesController.java @@ -1,10 +1,8 @@ package org.cryptomator.ui.preferences; import org.cryptomator.common.Environment; -import org.cryptomator.common.SemVerComparator; import org.cryptomator.common.settings.Settings; import org.cryptomator.ui.common.FxController; -import org.cryptomator.ui.controls.FormattedLabel; import org.cryptomator.ui.fxapp.UpdateChecker; import javax.inject.Inject; @@ -13,8 +11,10 @@ import javafx.application.Application; import javafx.beans.binding.Bindings; import javafx.beans.binding.BooleanBinding; import javafx.beans.binding.ObjectBinding; +import javafx.beans.property.BooleanProperty; import javafx.beans.property.ObjectProperty; import javafx.beans.property.ReadOnlyStringProperty; +import javafx.beans.property.SimpleBooleanProperty; import javafx.fxml.FXML; import javafx.scene.control.CheckBox; import javafx.scene.control.ContentDisplay; @@ -24,7 +24,6 @@ import javafx.util.Duration; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.time.format.FormatStyle; -import java.util.Comparator; import java.util.Locale; @@ -39,17 +38,15 @@ public class UpdatesPreferencesController implements FxController { private final UpdateChecker updateChecker; private final ObjectBinding checkForUpdatesButtonState; private final ReadOnlyStringProperty latestVersion; + private final ObjectProperty updateCheckDate; private final String currentVersion; private final BooleanBinding updateAvailable; - private final ObjectProperty updateCheckDateProperty; - private final Comparator versionComparator = new SemVerComparator(); + private final BooleanProperty upToDateLabelVisible = new SimpleBooleanProperty(false); private final ObjectProperty updateCheckStateProperty; /* FXML */ public CheckBox checkForUpdatesCheckbox; - public FormattedLabel updateCheckDateFormattedLabel; public HBox checkFailedHBox; - public FormattedLabel latestVersionFormattedLabel; public Label upToDateLabel; @Inject @@ -60,42 +57,23 @@ public class UpdatesPreferencesController implements FxController { this.updateChecker = updateChecker; this.checkForUpdatesButtonState = Bindings.when(updateChecker.checkingForUpdatesProperty()).then(ContentDisplay.LEFT).otherwise(ContentDisplay.TEXT_ONLY); this.latestVersion = updateChecker.latestVersionProperty(); + this.updateCheckDate = updateChecker.updateCheckTimeProperty(); this.currentVersion = updateChecker.getCurrentVersion(); - this.updateAvailable = Bindings.createBooleanBinding(() -> { - if (latestVersion.get() != null) { - return versionComparator.compare(currentVersion, latestVersion.get()) < 0; - } else { - return false; - } - }, latestVersion); - this.updateCheckDateProperty = updateChecker.updateCheckTimeProperty(); + this.updateAvailable = updateChecker.updateAvailableProperty(); this.updateCheckStateProperty = updateChecker.updateCheckStateProperty(); } public void initialize() { checkForUpdatesCheckbox.selectedProperty().bindBidirectional(settings.checkForUpdates); - DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM).withLocale(Locale.getDefault()); - updateCheckDateFormattedLabel.arg1Property().bind(Bindings.createStringBinding(() -> (!updateCheckDateProperty.get().equals(LocalDateTime.parse(Settings.DEFAULT_LAST_UPDATE_CHECK)) && latestVersionProperty().isNotNull().get()) ? updateCheckDateProperty.get().format(formatter) : "-", updateCheckDateProperty, latestVersionProperty())); - - BooleanBinding isUpdateCheckFailed = updateCheckStateProperty.isEqualTo(UpdateChecker.UpdateCheckState.CHECK_FAILED); - checkFailedHBox.managedProperty().bind(isUpdateCheckFailed); - checkFailedHBox.visibleProperty().bind(isUpdateCheckFailed); - - latestVersionFormattedLabel.arg1Property().bind(Bindings.createStringBinding(() -> (latestVersion.get() != null) ? latestVersion.get() : "-", latestVersion)); - BooleanBinding isUpdateSuccessfulAndCurrent = updateCheckStateProperty.isEqualTo(UpdateChecker.UpdateCheckState.CHECK_SUCCESSFUL).and(latestVersion.isEqualTo(currentVersion)); + updateCheckStateProperty.addListener((_, _, _) -> { if (isUpdateSuccessfulAndCurrent.get()) { - upToDateLabel.setVisible(true); - upToDateLabel.setManaged(true); - + upToDateLabelVisibleProperty().set(true); PauseTransition delay = new PauseTransition(Duration.seconds(5)); - delay.setOnFinished(_ -> { - upToDateLabel.setVisible(false); - upToDateLabel.setManaged(false); - }); + delay.setOnFinished(_ -> upToDateLabelVisibleProperty().set(false)); delay.play(); } }); @@ -131,13 +109,30 @@ public class UpdatesPreferencesController implements FxController { } public String getLatestVersion() { - return latestVersion.get(); + return latestVersion.isNotNull().get() ? latestVersion.get() : "-"; } public String getCurrentVersion() { return currentVersion; } + public ObjectProperty updateCheckDateProperty() { + return updateCheckDate; + } + + public String getUpdateCheckDate() { + DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM).withLocale(Locale.getDefault()); + return !updateCheckDate.get().equals(LocalDateTime.parse(Settings.DEFAULT_LAST_UPDATE_CHECK)) ? updateCheckDate.get().format(formatter) : "-"; + } + + public BooleanProperty upToDateLabelVisibleProperty() { + return upToDateLabelVisible; + } + + public final boolean isUpToDateLabelVisible() { + return upToDateLabelVisibleProperty().get(); + } + public BooleanBinding updateAvailableProperty() { return updateAvailable; } @@ -145,4 +140,13 @@ public class UpdatesPreferencesController implements FxController { public boolean isUpdateAvailable() { return updateAvailable.get(); } + + public BooleanBinding checkFailedProperty() { + return updateCheckStateProperty.isEqualTo(UpdateChecker.UpdateCheckState.CHECK_FAILED); + } + + public boolean isCheckFailed() { + return checkFailedProperty().get(); + } + } diff --git a/src/main/java/org/cryptomator/ui/updatereminder/UpdateReminderComponent.java b/src/main/java/org/cryptomator/ui/updatereminder/UpdateReminderComponent.java index d51d8df82..7a3d3077f 100644 --- a/src/main/java/org/cryptomator/ui/updatereminder/UpdateReminderComponent.java +++ b/src/main/java/org/cryptomator/ui/updatereminder/UpdateReminderComponent.java @@ -5,16 +5,21 @@ import dagger.Subcomponent; import org.cryptomator.common.settings.Settings; import org.cryptomator.ui.common.FxmlFile; import org.cryptomator.ui.common.FxmlScene; -import org.cryptomator.ui.fxapp.UpdateChecker; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import javafx.scene.Scene; import javafx.stage.Stage; import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; @UpdateReminderScoped @Subcomponent(modules = {UpdateReminderModule.class}) public interface UpdateReminderComponent { + Logger LOG = LoggerFactory.getLogger(UpdateReminderComponent.class); + @UpdateReminderWindow Stage window(); @@ -22,19 +27,24 @@ public interface UpdateReminderComponent { Lazy updateReminderScene(); Settings settings(); - UpdateChecker updateChecker(); default void checkAndShowUpdateReminderWindow() { - if (updateChecker().updateCheckTimeProperty().get().isBefore(LocalDateTime.now().minusDays(14)) && !settings().checkForUpdates.getValue()) { - Stage stage = window(); - stage.setScene(updateReminderScene().get()); - stage.sizeToScene(); - stage.show(); + try { + var dateTime = LocalDateTime.parse(settings().lastUpdateCheck.get(), DateTimeFormatter.ISO_DATE_TIME); + if (dateTime.isBefore(LocalDateTime.now().minusDays(14)) && !settings().checkForUpdates.getValue()) { + Stage stage = window(); + stage.setScene(updateReminderScene().get()); + stage.sizeToScene(); + stage.show(); + } + } catch (DateTimeParseException e) { + LOG.error("The date/time format is invalid:" + settings().lastUpdateCheck.get(), e); } } @Subcomponent.Factory interface Factory { + UpdateReminderComponent create(); } } \ No newline at end of file diff --git a/src/main/resources/fxml/preferences_updates.fxml b/src/main/resources/fxml/preferences_updates.fxml index 3db4824f5..f7b5383e0 100644 --- a/src/main/resources/fxml/preferences_updates.fxml +++ b/src/main/resources/fxml/preferences_updates.fxml @@ -22,8 +22,8 @@ - - + + @@ -34,7 +34,7 @@ - + -