added ui elements for update reminder

This commit is contained in:
Jan-Peter Klein
2023-07-10 13:04:07 +02:00
parent 2c984ad405
commit bc361ea592
11 changed files with 256 additions and 3 deletions

View File

@@ -41,6 +41,7 @@ public enum FxmlFile {
RECOVERYKEY_RESET_PASSWORD_SUCCESS("/fxml/recoverykey_reset_password_success.fxml"), //
RECOVERYKEY_SUCCESS("/fxml/recoverykey_success.fxml"), //
REMOVE_VAULT("/fxml/remove_vault.fxml"), //
UPDATE_REMINDER("/fxml/update_reminder.fxml"), //
UNLOCK_ENTER_PASSWORD("/fxml/unlock_enter_password.fxml"),
UNLOCK_INVALID_MOUNT_POINT("/fxml/unlock_invalid_mount_point.fxml"), //
UNLOCK_SELECT_MASTERKEYFILE("/fxml/unlock_select_masterkeyfile.fxml"), //

View File

@@ -67,6 +67,9 @@ public class FxApplication {
LOG.error("Failed to show main window", error);
return null;
});
if(!settings.checkForUpdates.getValue()){
appWindows.showUpdateReminderWindow();
}
launchEventHandler.startHandlingLaunchEvents();
autoUnlocker.tryUnlockForTimespan(2, TimeUnit.MINUTES);

View File

@@ -15,12 +15,13 @@ import org.cryptomator.ui.quit.QuitComponent;
import org.cryptomator.ui.traymenu.TrayMenuComponent;
import org.cryptomator.ui.unlock.UnlockComponent;
import org.cryptomator.ui.updatereminder.UpdateReminderComponent;
import javafx.scene.image.Image;
import java.io.IOException;
import java.io.InputStream;
@Module(includes = {UpdateCheckerModule.class}, subcomponents = {TrayMenuComponent.class, MainWindowComponent.class, PreferencesComponent.class, UnlockComponent.class, LockComponent.class, QuitComponent.class, ErrorComponent.class})
@Module(includes = {UpdateCheckerModule.class}, subcomponents = {TrayMenuComponent.class, MainWindowComponent.class, PreferencesComponent.class, UnlockComponent.class, LockComponent.class, QuitComponent.class, ErrorComponent.class, UpdateReminderComponent.class})
abstract class FxApplicationModule {
private static Image createImageFromResource(String resourceName) throws IOException {
@@ -52,4 +53,11 @@ abstract class FxApplicationModule {
static QuitComponent provideQuitComponent(QuitComponent.Builder builder) {
return builder.build();
}
@Provides
@FxApplicationScoped
static UpdateReminderComponent provideUpdateReminderComponent(UpdateReminderComponent.Builder builder) {
return builder.build();
}
}

View File

@@ -13,6 +13,7 @@ import org.cryptomator.ui.preferences.SelectedPreferencesTab;
import org.cryptomator.ui.quit.QuitComponent;
import org.cryptomator.ui.unlock.UnlockComponent;
import org.cryptomator.ui.unlock.UnlockWorkflow;
import org.cryptomator.ui.updatereminder.UpdateReminderComponent;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -43,19 +44,30 @@ public class FxApplicationWindows {
private final Lazy<PreferencesComponent> preferencesWindow;
private final QuitComponent.Builder quitWindowBuilder;
private final UnlockComponent.Factory unlockWorkflowFactory;
private final UpdateReminderComponent.Builder updateReminderWindowBuilder;
private final LockComponent.Factory lockWorkflowFactory;
private final ErrorComponent.Factory errorWindowFactory;
private final ExecutorService executor;
private final FilteredList<Window> visibleWindows;
@Inject
public FxApplicationWindows(@PrimaryStage Stage primaryStage, Optional<TrayIntegrationProvider> trayIntegration, Lazy<MainWindowComponent> mainWindow, Lazy<PreferencesComponent> preferencesWindow, QuitComponent.Builder quitWindowBuilder, UnlockComponent.Factory unlockWorkflowFactory, LockComponent.Factory lockWorkflowFactory, ErrorComponent.Factory errorWindowFactory, ExecutorService executor) {
public FxApplicationWindows(@PrimaryStage Stage primaryStage,
Optional<TrayIntegrationProvider> trayIntegration, //
Lazy<MainWindowComponent> mainWindow, //
Lazy<PreferencesComponent> preferencesWindow, //
QuitComponent.Builder quitWindowBuilder, //
UnlockComponent.Factory unlockWorkflowFactory, //
UpdateReminderComponent.Builder updateReminderWindowBuilder, //
LockComponent.Factory lockWorkflowFactory, //
ErrorComponent.Factory errorWindowFactory, //
ExecutorService executor) {
this.primaryStage = primaryStage;
this.trayIntegration = trayIntegration;
this.mainWindow = mainWindow;
this.preferencesWindow = preferencesWindow;
this.quitWindowBuilder = quitWindowBuilder;
this.unlockWorkflowFactory = unlockWorkflowFactory;
this.updateReminderWindowBuilder = updateReminderWindowBuilder;
this.lockWorkflowFactory = lockWorkflowFactory;
this.errorWindowFactory = errorWindowFactory;
this.executor = executor;
@@ -109,6 +121,10 @@ public class FxApplicationWindows {
CompletableFuture.runAsync(() -> quitWindowBuilder.build().showQuitWindow(response,forced), Platform::runLater);
}
public void showUpdateReminderWindow() {
CompletableFuture.runAsync(() -> updateReminderWindowBuilder.build().showUpdateReminderWindow(), Platform::runLater);
}
public CompletionStage<Void> startUnlockWorkflow(Vault vault, @Nullable Stage owner) {
return CompletableFuture.supplyAsync(() -> {
Preconditions.checkState(vault.stateProperty().transition(VaultState.Value.LOCKED, VaultState.Value.PROCESSING), "Vault not locked.");

View File

@@ -0,0 +1,37 @@
/*******************************************************************************
* Copyright (c) 2017 Skymatic UG (haftungsbeschränkt).
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the accompanying LICENSE file.
*******************************************************************************/
package org.cryptomator.ui.updatereminder;
import dagger.Lazy;
import dagger.Subcomponent;
import org.cryptomator.ui.common.FxmlFile;
import org.cryptomator.ui.common.FxmlScene;
import javafx.scene.Scene;
import javafx.stage.Stage;
@UpdateReminderScoped
@Subcomponent(modules = {UpdateReminderModule.class})
public interface UpdateReminderComponent {
@UpdateReminderWindow
Stage window();
@FxmlScene(FxmlFile.UPDATE_REMINDER)
Lazy<Scene> updateReminderScene();
default void showUpdateReminderWindow() {
Stage stage = window();
stage.setScene(updateReminderScene().get());
stage.sizeToScene();
stage.show();
}
@Subcomponent.Builder
interface Builder {
UpdateReminderComponent build();
}
}

View File

@@ -0,0 +1,42 @@
package org.cryptomator.ui.updatereminder;
import org.cryptomator.common.settings.Settings;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.fxapp.UpdateChecker;
import javax.inject.Inject;
import javafx.fxml.FXML;
import javafx.stage.Stage;
@UpdateReminderScoped
public class UpdateReminderController implements FxController {
private final Stage window;
private final Settings settings;
private final UpdateChecker updateChecker;
@Inject
UpdateReminderController(@UpdateReminderWindow Stage window, Settings settings, UpdateChecker updateChecker) {
this.window = window;
this.settings = settings;
this.updateChecker = updateChecker;
}
@FXML
public void cancel() {
window.close();
}
@FXML
public void once() {
updateChecker.checkForUpdatesNow();
window.close();
}
@FXML
public void automatically() {
settings.checkForUpdates.set(true);
updateChecker.checkForUpdatesNow();
window.close();
}
}

View File

@@ -0,0 +1,59 @@
package org.cryptomator.ui.updatereminder;
import dagger.Binds;
import dagger.Module;
import dagger.Provides;
import dagger.multibindings.IntoMap;
import org.cryptomator.ui.common.DefaultSceneFactory;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.common.FxControllerKey;
import org.cryptomator.ui.common.FxmlFile;
import org.cryptomator.ui.common.FxmlLoaderFactory;
import org.cryptomator.ui.common.FxmlScene;
import org.cryptomator.ui.common.StageFactory;
import javax.inject.Provider;
import javafx.scene.Scene;
import javafx.stage.Modality;
import javafx.stage.Stage;
import java.util.Map;
import java.util.ResourceBundle;
@Module
abstract class UpdateReminderModule {
@Provides
@UpdateReminderWindow
@UpdateReminderScoped
static FxmlLoaderFactory provideFxmlLoaderFactory(Map<Class<? extends FxController>, Provider<FxController>> factories, DefaultSceneFactory sceneFactory, ResourceBundle resourceBundle) {
return new FxmlLoaderFactory(factories, sceneFactory, resourceBundle);
}
@Provides
@UpdateReminderWindow
@UpdateReminderScoped
static Stage provideStage(StageFactory factory, ResourceBundle resourceBundle) {
Stage stage = factory.create();
stage.setTitle(resourceBundle.getString("updateReminder.title"));
stage.setMinWidth(450);
stage.setMinHeight(100);
stage.initModality(Modality.APPLICATION_MODAL);
return stage;
}
@Provides
@FxmlScene(FxmlFile.UPDATE_REMINDER)
@UpdateReminderScoped
static Scene provideUpdateReminderScene(@UpdateReminderWindow FxmlLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene(FxmlFile.UPDATE_REMINDER);
}
// ------------------
@Binds
@IntoMap
@FxControllerKey(UpdateReminderController.class)
abstract FxController bindUpdateReminderController(UpdateReminderController controller);
}

View File

@@ -0,0 +1,13 @@
package org.cryptomator.ui.updatereminder;
import javax.inject.Scope;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Scope
@Documented
@Retention(RetentionPolicy.RUNTIME)
@interface UpdateReminderScoped {
}

View File

@@ -0,0 +1,14 @@
package org.cryptomator.ui.updatereminder;
import javax.inject.Qualifier;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Qualifier
@Documented
@Retention(RUNTIME)
@interface UpdateReminderWindow {
}

View File

@@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.control.ButtonBar?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.Group?>
<?import javafx.scene.shape.Circle?>
<?import org.cryptomator.ui.controls.FontAwesome5IconView?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Button?>
<HBox xmlns:fx="http://javafx.com/fxml"
xmlns="http://javafx.com/javafx"
fx:controller="org.cryptomator.ui.updatereminder.UpdateReminderController"
minWidth="450"
maxWidth="450"
minHeight="145"
spacing="12"
alignment="TOP_LEFT">
<padding>
<Insets topRightBottomLeft="12"/>
</padding>
<children>
<VBox>
<HBox>
<Group>
<StackPane>
<padding>
<Insets topRightBottomLeft="6"/>
</padding>
<Circle styleClass="glyph-icon-primary" radius="24"/>
<FontAwesome5IconView styleClass="glyph-icon-white" glyph="EXCLAMATION" glyphSize="24"/>
</StackPane>
</Group>
<VBox HBox.hgrow="ALWAYS">
<Label styleClass="label-large" text="%updateReminder.title" wrapText="true">
<padding>
<Insets bottom="6" top="6"/>
</padding>
</Label>
<Label text="%updateReminder.message" wrapText="true"/>
<Region VBox.vgrow="ALWAYS" minHeight="18"/>
</VBox>
</HBox>
<ButtonBar buttonMinWidth="120" buttonOrder="CY">
<buttons>
<Button text="%updateReminder.notNow" ButtonBar.buttonData="CANCEL_CLOSE" cancelButton="true" onAction="#cancel"/>
<Button text="%updateReminder.yesOnce" ButtonBar.buttonData="YES" onAction="#once"/>
<Button text="%updateReminder.yesAutomatically" ButtonBar.buttonData="YES" defaultButton="true" onAction="#automatically" />
</buttons>
</ButtonBar>
</VBox>
</children>
</HBox>

View File

@@ -492,4 +492,10 @@ quit.lockAndQuitBtn=Lock and Quit
# Forced Quit
quit.forced.message=Some vaults could not be locked
quit.forced.description=Locking vaults was blocked by pending operations or open files. You can force lock remaining vaults, however interrupting I/O may result in the loss of unsaved data.
quit.forced.forceAndQuitBtn=Force and Quit
quit.forced.forceAndQuitBtn=Force and Quit
# Update Reminder
updateReminder.title=Check for Updates?
updateReminder.message=Would you like Cryptomator to check whether an update is available?
updateReminder.notNow=Not now
updateReminder.yesOnce=Yes, once
updateReminder.yesAutomatically=Yes, automatically