mirror of
https://github.com/cryptomator/cryptomator.git
synced 2026-05-17 02:01:27 +00:00
Hook up migration window
This commit is contained in:
@@ -68,6 +68,7 @@ public class Vault {
|
||||
private final BooleanBinding locked;
|
||||
private final BooleanBinding processing;
|
||||
private final BooleanBinding unlocked;
|
||||
private final BooleanBinding needsMigration;
|
||||
private final ObjectBinding<Path> accessPoint;
|
||||
|
||||
private volatile Volume volume;
|
||||
@@ -85,6 +86,7 @@ public class Vault {
|
||||
this.locked = Bindings.createBooleanBinding(this::isLocked, state);
|
||||
this.processing = Bindings.createBooleanBinding(this::isProcessing, state);
|
||||
this.unlocked = Bindings.createBooleanBinding(this::isUnlocked, state);
|
||||
this.needsMigration = Bindings.createBooleanBinding(this::isNeedsMigration, state);
|
||||
this.accessPoint = Bindings.createObjectBinding(this::getAccessPoint, state);
|
||||
}
|
||||
|
||||
@@ -215,6 +217,14 @@ public class Vault {
|
||||
public boolean isUnlocked() {
|
||||
return state.get() == VaultState.UNLOCKED;
|
||||
}
|
||||
|
||||
public BooleanBinding needsMigrationProperty() {
|
||||
return needsMigration;
|
||||
}
|
||||
|
||||
public boolean isNeedsMigration() {
|
||||
return state.get() == VaultState.NEEDS_MIGRATION;
|
||||
}
|
||||
|
||||
public StringBinding displayableNameProperty() {
|
||||
return displayableName;
|
||||
|
||||
@@ -9,6 +9,7 @@ public enum FxmlFile {
|
||||
ADDVAULT_SUCCESS("/fxml/addvault_success.fxml"), //
|
||||
CHANGEPASSWORD("/fxml/changepassword.fxml"), //
|
||||
MAIN_WINDOW("/fxml/main_window.fxml"), //
|
||||
MIGRATION_START("/fxml/migration_start.fxml"), //
|
||||
PREFERENCES("/fxml/preferences.fxml"), //
|
||||
QUIT("/fxml/quit.fxml"), //
|
||||
REMOVE_VAULT("/fxml/remove_vault.fxml"), //
|
||||
|
||||
@@ -12,6 +12,7 @@ public enum FontAwesome5Icon {
|
||||
EXCLAMATION_TRIANGLE("\uF071"), //
|
||||
EYE("\uF06E"), //
|
||||
EYE_SLASH("\uF070"), //
|
||||
FILE_IMPORT("\uF56F"), //
|
||||
FOLDER_OPEN("\uF07C"), //
|
||||
HDD("\uF0A0"), //
|
||||
KEY("\uF084"), //
|
||||
|
||||
@@ -17,6 +17,7 @@ import org.cryptomator.ui.common.FxController;
|
||||
import org.cryptomator.ui.common.FxControllerKey;
|
||||
import org.cryptomator.ui.common.FxmlFile;
|
||||
import org.cryptomator.ui.common.FxmlScene;
|
||||
import org.cryptomator.ui.migration.MigrationComponent;
|
||||
import org.cryptomator.ui.removevault.RemoveVaultComponent;
|
||||
import org.cryptomator.ui.vaultoptions.VaultOptionsComponent;
|
||||
import org.cryptomator.ui.wrongfilealert.WrongFileAlertComponent;
|
||||
@@ -27,7 +28,7 @@ import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
@Module(subcomponents = {AddVaultWizardComponent.class, RemoveVaultComponent.class, VaultOptionsComponent.class, WrongFileAlertComponent.class})
|
||||
@Module(subcomponents = {AddVaultWizardComponent.class, MigrationComponent.class, RemoveVaultComponent.class, VaultOptionsComponent.class, WrongFileAlertComponent.class})
|
||||
abstract class MainWindowModule {
|
||||
|
||||
@Provides
|
||||
|
||||
@@ -13,6 +13,7 @@ import org.cryptomator.ui.common.FxController;
|
||||
import org.cryptomator.ui.common.Tasks;
|
||||
import org.cryptomator.ui.controls.FontAwesome5Icon;
|
||||
import org.cryptomator.ui.fxapp.FxApplication;
|
||||
import org.cryptomator.ui.migration.MigrationComponent;
|
||||
import org.cryptomator.ui.vaultoptions.VaultOptionsComponent;
|
||||
import org.fxmisc.easybind.EasyBind;
|
||||
import org.slf4j.Logger;
|
||||
@@ -32,15 +33,17 @@ public class VaultDetailController implements FxController {
|
||||
private final ExecutorService executor;
|
||||
private final FxApplication application;
|
||||
private final VaultOptionsComponent.Builder vaultOptionsWindow;
|
||||
private final MigrationComponent.Builder vaultMigrationWindow;
|
||||
|
||||
@Inject
|
||||
VaultDetailController(ObjectProperty<Vault> vault, ExecutorService executor, FxApplication application, VaultOptionsComponent.Builder vaultOptionsWindow) {
|
||||
VaultDetailController(ObjectProperty<Vault> vault, ExecutorService executor, FxApplication application, VaultOptionsComponent.Builder vaultOptionsWindow, MigrationComponent.Builder vaultMigrationWindow) {
|
||||
this.vault = vault;
|
||||
this.glyph = EasyBind.select(vault).selectObject(Vault::stateProperty).map(this::getGlyphForVaultState).orElse(FontAwesome5Icon.EXCLAMATION_TRIANGLE);
|
||||
this.executor = executor;
|
||||
this.application = application;
|
||||
this.vaultOptionsWindow = vaultOptionsWindow;
|
||||
this.anyVaultSelected = vault.isNotNull();
|
||||
this.vaultMigrationWindow = vaultMigrationWindow;
|
||||
}
|
||||
|
||||
private FontAwesome5Icon getGlyphForVaultState(VaultState state) {
|
||||
@@ -83,12 +86,17 @@ public class VaultDetailController implements FxController {
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void revealStorageLocation(ActionEvent actionEvent) {
|
||||
public void showVaultMigrator() {
|
||||
vaultMigrationWindow.vault(vault.get()).build().showMigrationWindow();
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void revealStorageLocation() {
|
||||
application.getHostServices().showDocument(vault.get().getPath().toUri().toString());
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void revealAccessLocation(ActionEvent actionEvent) {
|
||||
public void revealAccessLocation() {
|
||||
try {
|
||||
vault.get().reveal();
|
||||
} catch (Volume.VolumeException e) {
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
package org.cryptomator.ui.migration;
|
||||
|
||||
import dagger.BindsInstance;
|
||||
import dagger.Lazy;
|
||||
import dagger.Subcomponent;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.stage.Stage;
|
||||
import org.cryptomator.common.vaults.Vault;
|
||||
import org.cryptomator.ui.common.FxmlFile;
|
||||
import org.cryptomator.ui.common.FxmlScene;
|
||||
|
||||
@MigrationScoped
|
||||
@Subcomponent(modules = {MigrationModule.class})
|
||||
public interface MigrationComponent {
|
||||
|
||||
@MigrationWindow
|
||||
Stage window();
|
||||
|
||||
@FxmlScene(FxmlFile.MIGRATION_START)
|
||||
Lazy<Scene> scene();
|
||||
|
||||
default Stage showMigrationWindow() {
|
||||
Stage stage = window();
|
||||
stage.setScene(scene().get());
|
||||
stage.show();
|
||||
return stage;
|
||||
}
|
||||
|
||||
@Subcomponent.Builder
|
||||
interface Builder {
|
||||
|
||||
@BindsInstance
|
||||
Builder vault(@MigrationWindow Vault vault);
|
||||
|
||||
MigrationComponent build();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package org.cryptomator.ui.migration;
|
||||
|
||||
import dagger.Binds;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import dagger.multibindings.IntoMap;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.image.Image;
|
||||
import javafx.scene.input.KeyCode;
|
||||
import javafx.scene.input.KeyCodeCombination;
|
||||
import javafx.scene.input.KeyCombination;
|
||||
import javafx.stage.Modality;
|
||||
import javafx.stage.Stage;
|
||||
import org.cryptomator.ui.common.FXMLLoaderFactory;
|
||||
import org.cryptomator.ui.common.FxController;
|
||||
import org.cryptomator.ui.common.FxControllerKey;
|
||||
import org.cryptomator.ui.common.FxmlFile;
|
||||
import org.cryptomator.ui.common.FxmlScene;
|
||||
import org.cryptomator.ui.mainwindow.MainWindow;
|
||||
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Provider;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
@Module
|
||||
abstract class MigrationModule {
|
||||
|
||||
@Provides
|
||||
@MigrationWindow
|
||||
@MigrationScoped
|
||||
static FXMLLoaderFactory provideFxmlLoaderFactory(Map<Class<? extends FxController>, Provider<FxController>> factories, ResourceBundle resourceBundle) {
|
||||
return new FXMLLoaderFactory(factories, resourceBundle);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@MigrationWindow
|
||||
@MigrationScoped
|
||||
static Stage provideStage(@MainWindow Stage owner, ResourceBundle resourceBundle, @Named("windowIcon") Optional<Image> windowIcon) {
|
||||
Stage stage = new Stage();
|
||||
stage.setTitle(resourceBundle.getString("unlock.title"));
|
||||
stage.setResizable(false);
|
||||
stage.initModality(Modality.WINDOW_MODAL);
|
||||
stage.initOwner(owner);
|
||||
windowIcon.ifPresent(stage.getIcons()::add);
|
||||
return stage;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@FxmlScene(FxmlFile.MIGRATION_START)
|
||||
@MigrationScoped
|
||||
static Scene provideMigrationStartScene(@MigrationWindow FXMLLoaderFactory fxmlLoaders, @MigrationWindow Stage window) {
|
||||
Scene scene = fxmlLoaders.createScene("/fxml/migration_start.fxml"); // TODO rename fxml file
|
||||
|
||||
KeyCombination cmdW = new KeyCodeCombination(KeyCode.W, KeyCombination.SHORTCUT_DOWN);
|
||||
scene.getAccelerators().put(cmdW, window::close);
|
||||
|
||||
return scene;
|
||||
}
|
||||
|
||||
|
||||
// ------------------
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@FxControllerKey(MigrationStartController.class)
|
||||
abstract FxController bindMigrationStartController(MigrationStartController controller);
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package org.cryptomator.ui.migration;
|
||||
|
||||
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 MigrationScoped {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package org.cryptomator.ui.migration;
|
||||
|
||||
import dagger.Lazy;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.stage.Stage;
|
||||
import org.cryptomator.common.vaults.Vault;
|
||||
import org.cryptomator.ui.common.FxController;
|
||||
import org.cryptomator.ui.common.FxmlFile;
|
||||
import org.cryptomator.ui.common.FxmlScene;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
@MigrationScoped
|
||||
public class MigrationStartController implements FxController {
|
||||
|
||||
private final Stage window;
|
||||
private final Vault vault;
|
||||
private final Lazy<Scene> successScene;
|
||||
|
||||
@Inject
|
||||
public MigrationStartController(@MigrationWindow Stage window, @MigrationWindow Vault vault, @FxmlScene(FxmlFile.MIGRATION_START) Lazy<Scene> successScene) {
|
||||
this.window = window;
|
||||
this.vault = vault;
|
||||
this.successScene = successScene;
|
||||
}
|
||||
|
||||
public void initialize() {
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void cancel() {
|
||||
window.close();
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void proceed() {
|
||||
|
||||
}
|
||||
|
||||
/* Getter/Setter */
|
||||
|
||||
public Vault getVault() {
|
||||
return vault;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package org.cryptomator.ui.migration;
|
||||
|
||||
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)
|
||||
public @interface MigrationWindow {
|
||||
|
||||
}
|
||||
45
main/ui/src/main/resources/fxml/migration_start.fxml
Normal file
45
main/ui/src/main/resources/fxml/migration_start.fxml
Normal file
@@ -0,0 +1,45 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.control.Button?>
|
||||
<?import javafx.scene.control.ButtonBar?>
|
||||
<?import javafx.scene.control.CheckBox?>
|
||||
<?import javafx.scene.layout.HBox?>
|
||||
<?import javafx.scene.layout.StackPane?>
|
||||
<?import javafx.scene.layout.VBox?>
|
||||
<?import javafx.scene.shape.Circle?>
|
||||
<?import org.cryptomator.ui.controls.FontAwesome5IconView?>
|
||||
<?import org.cryptomator.ui.controls.FormattedLabel?>
|
||||
<VBox xmlns="http://javafx.com/javafx"
|
||||
xmlns:fx="http://javafx.com/fxml"
|
||||
fx:controller="org.cryptomator.ui.migration.MigrationStartController"
|
||||
minWidth="400"
|
||||
maxWidth="400"
|
||||
minHeight="145"
|
||||
spacing="12">
|
||||
<padding>
|
||||
<Insets topRightBottomLeft="12"/>
|
||||
</padding>
|
||||
<children>
|
||||
<HBox spacing="12" alignment="CENTER_LEFT" VBox.vgrow="ALWAYS">
|
||||
<StackPane alignment="CENTER" HBox.hgrow="NEVER">
|
||||
<Circle styleClass="glyph-icon-primary" radius="24"/>
|
||||
<FontAwesome5IconView styleClass="glyph-icon-white" glyph="FILE_IMPORT" glyphSize="24"/>
|
||||
</StackPane>
|
||||
|
||||
<VBox spacing="6" HBox.hgrow="ALWAYS">
|
||||
<FormattedLabel format="TODO Your vault "%s" needs to be updated to a newer format. Before proceeding, make sure there is no pending synchronization affecting this vault." arg1="${controller.vault.displayableName}" wrapText="true" />
|
||||
<CheckBox fx:id="confirmSyncDone" text="TODO Yes, my vault is fully synced"/>
|
||||
</VBox>
|
||||
</HBox>
|
||||
|
||||
<VBox alignment="BOTTOM_CENTER" VBox.vgrow="ALWAYS">
|
||||
<ButtonBar buttonMinWidth="120" buttonOrder="+CX">
|
||||
<buttons>
|
||||
<Button text="%generic.button.done" ButtonBar.buttonData="CANCEL_CLOSE" cancelButton="true" onAction="#cancel"/>
|
||||
<Button text="%generic.button.next" ButtonBar.buttonData="NEXT_FORWARD" defaultButton="true" onAction="#proceed" disable="${!confirmSyncDone.selected}"/>
|
||||
</buttons>
|
||||
</ButtonBar>
|
||||
</VBox>
|
||||
</children>
|
||||
</VBox>
|
||||
@@ -87,6 +87,13 @@
|
||||
</Button>
|
||||
</VBox>
|
||||
|
||||
<!-- TODO we might want to split this fxml file into one file per vault state -->
|
||||
<Button styleClass="button-large" text="TODO Upgrade Vault" minWidth="120" onAction="#showVaultMigrator" visible="${controller.vault.needsMigration}">
|
||||
<graphic>
|
||||
<FontAwesome5IconView glyph="FILE_IMPORT" glyphSize="15"/>
|
||||
</graphic>
|
||||
</Button>
|
||||
|
||||
<Region VBox.vgrow="ALWAYS"/>
|
||||
|
||||
<VBox spacing="6" visible="${controller.vault.unlocked}" managed="${controller.vault.unlocked}">
|
||||
|
||||
Reference in New Issue
Block a user