Ver Fonte

recover button now in VaultListController

Jan-Peter Klein há 1 mês atrás
pai
commit
edc308ccd1

+ 63 - 0
src/main/java/org/cryptomator/ui/addvaultwizard/AddVaultWizardComponent.java

@@ -7,13 +7,28 @@ package org.cryptomator.ui.addvaultwizard;
 
 import dagger.Lazy;
 import dagger.Subcomponent;
+import org.cryptomator.common.recovery.RecoveryActionType;
+import org.cryptomator.common.vaults.Vault;
+import org.cryptomator.common.vaults.VaultComponent;
+import org.cryptomator.common.vaults.VaultListManager;
+import org.cryptomator.common.vaults.VaultState;
+import org.cryptomator.integrations.mount.MountService;
 import org.cryptomator.ui.common.FxmlFile;
 import org.cryptomator.ui.common.FxmlScene;
+import org.cryptomator.ui.dialogs.Dialogs;
+import org.cryptomator.ui.recoverykey.RecoveryKeyComponent;
 
+import javafx.beans.property.SimpleObjectProperty;
 import javafx.scene.Scene;
+import javafx.stage.DirectoryChooser;
 import javafx.stage.Stage;
+import javafx.stage.Window;
+import java.io.File;
+import java.util.List;
 import java.util.ResourceBundle;
 
+import static org.cryptomator.ui.addvaultwizard.ChooseExistingVaultController.prepareVault;
+
 @AddVaultWizardScoped
 @Subcomponent(modules = {AddVaultModule.class})
 public interface AddVaultWizardComponent {
@@ -23,9 +38,13 @@ public interface AddVaultWizardComponent {
 
 	@FxmlScene(FxmlFile.ADDVAULT_NEW_NAME)
 	Lazy<Scene> sceneNew();
+
 	@FxmlScene(FxmlFile.ADDVAULT_EXISTING)
 	Lazy<Scene> sceneExisting();
 
+	@FxmlScene(FxmlFile.ADDVAULT_SUCCESS)
+	Lazy<Scene> sceneSuccess();
+
 	default void showAddNewVaultWizard(ResourceBundle resourceBundle) {
 		Stage stage = window();
 		stage.setScene(sceneNew().get());
@@ -42,6 +61,50 @@ public interface AddVaultWizardComponent {
 		stage.show();
 	}
 
+	default void showRecoverExistingVaultWizard(Window mainWindow, //
+												Dialogs dialogs, //
+												VaultComponent.Factory vaultComponentFactory, //
+												List<MountService> mountServices, //
+												VaultListManager vaultListManager, //
+												RecoveryKeyComponent.Factory recoveryKeyWindow) {
+		Stage stage = window();
+		DirectoryChooser directoryChooser = new DirectoryChooser();
+
+		while (true) {
+			File selectedDirectory = directoryChooser.showDialog(mainWindow);
+			if (selectedDirectory == null) {
+				return;
+			}
+
+			boolean hasSubfolderD = new File(selectedDirectory, "d").isDirectory();
+			if (!hasSubfolderD) {
+				dialogs.prepareNoDDirectorySelectedDialog(stage).build().showAndWait();
+				continue;
+			}
+
+			Vault preparedVault = prepareVault(selectedDirectory, vaultComponentFactory, mountServices);
+
+			if (!vaultListManager.containsVault(preparedVault.getPath())) {
+				vaultListManager.addVault(preparedVault);
+				dialogs.prepareRecoveryVaultAdded(stage).setOkAction(Stage::close).build().showAndWait();
+			}
+
+			VaultListManager.redetermineVaultState(preparedVault);
+			VaultState.Value state = preparedVault.getState();
+
+			switch (state) {
+				case VAULT_CONFIG_MISSING -> recoveryKeyWindow.create(preparedVault, stage, new SimpleObjectProperty<>(RecoveryActionType.RESTORE_VAULT_CONFIG)) //
+						.showOnboardingDialogWindow();
+				case ALL_MISSING -> recoveryKeyWindow.create(preparedVault, stage, new SimpleObjectProperty<>(RecoveryActionType.RESTORE_ALL)) //
+						.showOnboardingDialogWindow();
+				default -> dialogs.prepareRecoveryVaultAlreadyExists(stage)//
+						.setOkAction(Stage::close)//
+						.build().showAndWait();
+			}
+			break;
+		}
+	}
+
 	@Subcomponent.Builder
 	interface Builder {
 

+ 18 - 73
src/main/java/org/cryptomator/ui/addvaultwizard/ChooseExistingVaultController.java

@@ -1,16 +1,30 @@
 package org.cryptomator.ui.addvaultwizard;
 
+import dagger.Lazy;
+import org.apache.commons.lang3.SystemUtils;
+import org.cryptomator.common.settings.VaultSettings;
+import org.cryptomator.common.vaults.Vault;
+import org.cryptomator.common.vaults.VaultComponent;
+import org.cryptomator.common.vaults.VaultConfigCache;
+import org.cryptomator.common.vaults.VaultListManager;
+import org.cryptomator.integrations.mount.MountService;
+import org.cryptomator.integrations.uiappearance.Theme;
+import org.cryptomator.ui.common.FxController;
+import org.cryptomator.ui.common.FxmlFile;
+import org.cryptomator.ui.common.FxmlScene;
+import org.cryptomator.ui.fxapp.FxApplicationStyle;
+import org.cryptomator.ui.fxapp.FxApplicationWindows;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 import javax.inject.Inject;
 import javafx.beans.property.BooleanProperty;
 import javafx.beans.property.ObjectProperty;
 import javafx.beans.property.SimpleBooleanProperty;
-import javafx.beans.property.SimpleObjectProperty;
 import javafx.beans.value.ObservableValue;
 import javafx.fxml.FXML;
 import javafx.scene.Scene;
-import javafx.scene.control.CheckBox;
 import javafx.scene.image.Image;
-import javafx.stage.DirectoryChooser;
 import javafx.stage.FileChooser;
 import javafx.stage.Stage;
 import java.io.File;
@@ -23,27 +37,6 @@ import java.util.ResourceBundle;
 import static org.cryptomator.common.Constants.CRYPTOMATOR_FILENAME_GLOB;
 import static org.cryptomator.common.vaults.VaultState.Value.LOCKED;
 
-import dagger.Lazy;
-import org.apache.commons.lang3.SystemUtils;
-import org.cryptomator.common.recovery.RecoveryActionType;
-import org.cryptomator.common.settings.VaultSettings;
-import org.cryptomator.common.vaults.Vault;
-import org.cryptomator.common.vaults.VaultComponent;
-import org.cryptomator.common.vaults.VaultConfigCache;
-import org.cryptomator.common.vaults.VaultListManager;
-import org.cryptomator.common.vaults.VaultState;
-import org.cryptomator.integrations.mount.MountService;
-import org.cryptomator.integrations.uiappearance.Theme;
-import org.cryptomator.ui.common.FxController;
-import org.cryptomator.ui.common.FxmlFile;
-import org.cryptomator.ui.common.FxmlScene;
-import org.cryptomator.ui.dialogs.Dialogs;
-import org.cryptomator.ui.fxapp.FxApplicationStyle;
-import org.cryptomator.ui.fxapp.FxApplicationWindows;
-import org.cryptomator.ui.recoverykey.RecoveryKeyComponent;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
 @AddVaultWizardScoped
 public class ChooseExistingVaultController implements FxController {
 
@@ -57,13 +50,6 @@ public class ChooseExistingVaultController implements FxController {
 	private final VaultListManager vaultListManager;
 	private final ResourceBundle resourceBundle;
 	private final ObservableValue<Image> screenshot;
-	private final Dialogs dialogs;
-	private final VaultComponent.Factory vaultComponentFactory;
-	private final RecoveryKeyComponent.Factory recoveryKeyWindow;
-	private final List<MountService> mountServices;
-
-	@FXML
-	private CheckBox restoreCheckBox;
 
 	private final BooleanProperty restoreButtonVisible = new SimpleBooleanProperty(false);
 
@@ -76,11 +62,7 @@ public class ChooseExistingVaultController implements FxController {
 								  @AddVaultWizardWindow ObjectProperty<Vault> vault, //
 								  VaultListManager vaultListManager, //
 								  ResourceBundle resourceBundle, //
-								  FxApplicationStyle applicationStyle, //
-								  RecoveryKeyComponent.Factory recoveryKeyWindow, //
-								  VaultComponent.Factory vaultComponentFactory, //
-								  List<MountService> mountServices, //
-								  Dialogs dialogs) {
+								  FxApplicationStyle applicationStyle) {
 		this.window = window;
 		this.successScene = successScene;
 		this.appWindows = appWindows;
@@ -89,14 +71,6 @@ public class ChooseExistingVaultController implements FxController {
 		this.vaultListManager = vaultListManager;
 		this.resourceBundle = resourceBundle;
 		this.screenshot = applicationStyle.appliedThemeProperty().map(this::selectScreenshot);
-		this.recoveryKeyWindow = recoveryKeyWindow;
-		this.vaultComponentFactory = vaultComponentFactory;
-		this.mountServices = mountServices;
-		this.dialogs = dialogs;
-	}
-
-	public void initialize() {
-		restoreButtonVisible.bind(restoreCheckBox.selectedProperty());
 	}
 
 	private Image selectScreenshot(Theme theme) {
@@ -131,35 +105,6 @@ public class ChooseExistingVaultController implements FxController {
 		}
 	}
 
-	@FXML
-	public void restoreVaultConfigWithRecoveryKey() {
-		DirectoryChooser directoryChooser = new DirectoryChooser();
-
-		File selectedDirectory = directoryChooser.showDialog(window);
-		if (selectedDirectory == null) {
-			return;
-		}
-
-		boolean hasSubfolderD = new File(selectedDirectory, "d").isDirectory();
-		if (!hasSubfolderD) {
-			dialogs.prepareNoDDirectorySelectedDialog(window).build().showAndWait();
-			return;
-		}
-
-		Vault preparedVault = prepareVault(selectedDirectory, vaultComponentFactory, mountServices);
-		VaultListManager.redetermineVaultState(preparedVault);
-		VaultState.Value state = preparedVault.getState();
-		switch (state) {
-			case VAULT_CONFIG_MISSING -> recoveryKeyWindow.create(preparedVault, window, new SimpleObjectProperty<>(RecoveryActionType.RESTORE_VAULT_CONFIG)).showOnboardingDialogWindow();
-			case ALL_MISSING -> recoveryKeyWindow.create(preparedVault, window, new SimpleObjectProperty<>(RecoveryActionType.RESTORE_ALL)).showOnboardingDialogWindow();
-			default -> {
-				vaultListManager.addVault(preparedVault);
-				vault.set(preparedVault);
-				window.setScene(successScene.get());
-			}
-		}
-	}
-
 	public static Vault prepareVault(File selectedDirectory, VaultComponent.Factory vaultComponentFactory, List<MountService> mountServices) {
 		Path selectedPath = selectedDirectory.toPath();
 		VaultSettings vaultSettings = VaultSettings.withRandomId();

+ 1 - 0
src/main/java/org/cryptomator/ui/controls/FontAwesome5Icon.java

@@ -6,6 +6,7 @@ package org.cryptomator.ui.controls;
 public enum FontAwesome5Icon {
 	ANCHOR("\uF13D"), //
 	ARROW_UP("\uF062"), //
+	ARROWS_ROTATE("\uF021"),
 	BAN("\uF05E"), //
 	BELL("\uF0F3"), //
 	BUG("\uF188"), //

+ 19 - 1
src/main/java/org/cryptomator/ui/dialogs/Dialogs.java

@@ -58,6 +58,23 @@ public class Dialogs {
 				.setOkButtonKey(BUTTON_KEY_CLOSE);
 	}
 
+	public SimpleDialog.Builder prepareRecoveryVaultAdded(Stage window) {
+		return createDialogBuilder().setOwner(window) //
+				.setTitleKey("recoveryKey.recoverExisting.title") //
+				.setMessageKey("recoveryKey.recoverExisting.message") //
+				.setDescriptionKey("recoveryKey.recoverExisting.description") //
+				.setIcon(FontAwesome5Icon.EXCLAMATION)//
+				.setOkButtonKey(BUTTON_KEY_CLOSE);
+	}
+	public SimpleDialog.Builder prepareRecoveryVaultAlreadyExists(Stage window) {
+		return createDialogBuilder().setOwner(window) //
+				.setTitleKey("recoveryKey.alreadyExists.title") //
+				.setMessageKey("recoveryKey.alreadyExists.message") //
+				.setDescriptionKey("recoveryKey.alreadyExists.description") //
+				.setIcon(FontAwesome5Icon.EXCLAMATION)//
+				.setOkButtonKey(BUTTON_KEY_CLOSE);
+	}
+
 	public SimpleDialog.Builder prepareRecoverPasswordSuccess(Stage window, Stage owner, ResourceBundle resourceBundle) {
 		return createDialogBuilder()
 				.setOwner(window) //
@@ -67,7 +84,8 @@ public class Dialogs {
 				.setIcon(FontAwesome5Icon.CHECK)
 				.setOkAction(stage -> {
 					stage.close();
-					if (owner.getTitle().equals(resourceBundle.getString("addvaultwizard.existing.title"))) {
+					String ownerTitle = owner.getTitle();
+					if (ownerTitle != null && ownerTitle.equals(resourceBundle.getString("addvaultwizard.existing.title"))) {
 						owner.close();
 					}
 				})

+ 19 - 0
src/main/java/org/cryptomator/ui/mainwindow/VaultListController.java

@@ -3,9 +3,11 @@ package org.cryptomator.ui.mainwindow;
 import org.apache.commons.lang3.SystemUtils;
 import org.cryptomator.common.settings.Settings;
 import org.cryptomator.common.vaults.Vault;
+import org.cryptomator.common.vaults.VaultComponent;
 import org.cryptomator.common.vaults.VaultListManager;
 import org.cryptomator.cryptofs.CryptoFileSystemProvider;
 import org.cryptomator.cryptofs.DirStructure;
+import org.cryptomator.integrations.mount.MountService;
 import org.cryptomator.ui.addvaultwizard.AddVaultWizardComponent;
 import org.cryptomator.ui.common.FxController;
 import org.cryptomator.ui.common.VaultService;
@@ -13,6 +15,7 @@ import org.cryptomator.ui.dialogs.Dialogs;
 import org.cryptomator.ui.fxapp.FxFSEventList;
 import org.cryptomator.ui.fxapp.FxApplicationWindows;
 import org.cryptomator.ui.preferences.SelectedPreferencesTab;
+import org.cryptomator.ui.recoverykey.RecoveryKeyComponent;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -42,6 +45,7 @@ import java.io.File;
 import java.io.IOException;
 import java.nio.file.Path;
 import java.util.EnumSet;
+import java.util.List;
 import java.util.Optional;
 import java.util.ResourceBundle;
 import java.util.Set;
@@ -75,6 +79,10 @@ public class VaultListController implements FxController {
 	private final ObservableValue<Double> cellSize;
 	private final Dialogs dialogs;
 
+	private final VaultComponent.Factory vaultComponentFactory;
+	private final RecoveryKeyComponent.Factory recoveryKeyWindow;
+	private final List<MountService> mountServices;
+
 	public ListView<Vault> vaultList;
 	public StackPane root;
 	@FXML
@@ -94,6 +102,9 @@ public class VaultListController implements FxController {
 						FxApplicationWindows appWindows, //
 						Settings settings, //
 						Dialogs dialogs, //
+						RecoveryKeyComponent.Factory recoveryKeyWindow, //
+						VaultComponent.Factory vaultComponentFactory, //
+						List<MountService> mountServices, //
 						FxFSEventList fxFSEventList) {
 		this.mainWindow = mainWindow;
 		this.vaults = vaults;
@@ -105,6 +116,9 @@ public class VaultListController implements FxController {
 		this.resourceBundle = resourceBundle;
 		this.appWindows = appWindows;
 		this.dialogs = dialogs;
+		this.recoveryKeyWindow = recoveryKeyWindow;
+		this.vaultComponentFactory = vaultComponentFactory;
+		this.mountServices = mountServices;
 
 		this.emptyVaultList = Bindings.isEmpty(vaults);
 		this.unreadEvents = fxFSEventList.unreadEventsProperty();
@@ -214,6 +228,11 @@ public class VaultListController implements FxController {
 		addVaultWizard.build().showAddExistingVaultWizard(resourceBundle);
 	}
 
+	@FXML
+	public void didClickRecoverExistingVault() {
+		addVaultWizard.build().showRecoverExistingVaultWizard(mainWindow, dialogs, vaultComponentFactory,mountServices,vaultListManager,recoveryKeyWindow);
+	}
+
 	private void pressedShortcutToRemoveVault() {
 		final var vault = selectedVault.get();
 		if (vault != null && EnumSet.of(LOCKED, MISSING, ERROR, NEEDS_MIGRATION).contains(vault.getState())) {

+ 6 - 11
src/main/resources/fxml/addvault_existing.fxml

@@ -3,7 +3,6 @@
 <?import javafx.geometry.Insets?>
 <?import javafx.scene.control.Button?>
 <?import javafx.scene.control.ButtonBar?>
-<?import javafx.scene.control.CheckBox?>
 <?import javafx.scene.control.Label?>
 <?import javafx.scene.image.ImageView?>
 <?import javafx.scene.layout.Region?>
@@ -12,25 +11,21 @@
 	  xmlns="http://javafx.com/javafx"
 	  fx:controller="org.cryptomator.ui.addvaultwizard.ChooseExistingVaultController"
 	  prefWidth="450"
-	  prefHeight="480">
+	  prefHeight="450"
+	  spacing="24"
+	  alignment="CENTER">
 	<padding>
 		<Insets topRightBottomLeft="24"/>
 	</padding>
 	<children>
 		<ImageView VBox.vgrow="ALWAYS" fitWidth="400" preserveRatio="true" smooth="true" image="${controller.screenshot}"/>
 
-		<Label text="%addvaultwizard.existing.instruction" wrapText="true">
-			<padding>
-				<Insets bottom="6" top="6"/>
-			</padding>
-		</Label>
+		<Label text="%addvaultwizard.existing.instruction" wrapText="true" labelFor="$finishButton"/>
 
-		<CheckBox fx:id="restoreCheckBox" text="%addvaultwizard.existing.instruction.restore" wrapText="true"/>
 		<Region VBox.vgrow="ALWAYS"/>
-		<ButtonBar buttonMinWidth="120" buttonOrder="+CX">
+		<ButtonBar buttonMinWidth="120" buttonOrder="+X">
 			<buttons>
-				<Button text="%addvaultwizard.existing.restore" ButtonBar.buttonData="NEXT_FORWARD" onAction="#restoreVaultConfigWithRecoveryKey" visible="${controller.restoreButtonVisible}"/>
-				<Button text="%addvaultwizard.existing.chooseBtn" ButtonBar.buttonData="NEXT_FORWARD" onAction="#chooseFileAndNext" defaultButton="true"/>
+				<Button fx:id="finishButton" text="%addvaultwizard.existing.chooseBtn" ButtonBar.buttonData="NEXT_FORWARD" onAction="#chooseFileAndNext" defaultButton="true"/>
 			</buttons>
 		</ButtonBar>
 	</children>

+ 5 - 0
src/main/resources/fxml/vault_list.fxml

@@ -80,6 +80,11 @@
 						<FontAwesome5IconView glyph="FOLDER_OPEN" textAlignment="CENTER" wrappingWidth="14"/>
 					</graphic>
 				</MenuItem>
+				<MenuItem styleClass="dropdown-button-context-menu-item" text="%main.vaultlist.addVaultBtn.menuItemRecover" onAction="#didClickRecoverExistingVault">
+					<graphic>
+						<FontAwesome5IconView glyph="ARROWS_ROTATE" textAlignment="CENTER" wrappingWidth="14"/>
+					</graphic>
+				</MenuItem>
 			</items>
 		</ContextMenu>
 	</fx:define>

+ 10 - 1
src/main/resources/i18n/strings.properties

@@ -96,7 +96,7 @@ addvault.new.readme.accessLocation.3=Any files added to this volume will be encr
 addvault.new.readme.accessLocation.4=Feel free to remove this file.
 ## Existing
 addvaultwizard.existing.title=Add Existing Vault
-addvaultwizard.existing.instruction=Choose the "vault.cryptomator" file of your existing vault. If only a file named "masterkey.cryptomator" exists, select that instead. If your vault.cryptomator lost you can recover it with your RecoveryKey.
+addvaultwizard.existing.instruction=Choose the "vault.cryptomator" file of your existing vault. If only a file named "masterkey.cryptomator" exists, select that instead.
 addvaultwizard.existing.instruction.restore=If your vault.cryptomator file went missing you can enable restore mode here.
 addvaultwizard.existing.restore=Restore…
 addvaultwizard.existing.chooseBtn=Choose…
@@ -404,6 +404,7 @@ main.vaultlist.contextMenu.vaultoptions=Show Vault Options
 main.vaultlist.contextMenu.reveal=Reveal Drive
 main.vaultlist.addVaultBtn.menuItemNew=Create New Vault...
 main.vaultlist.addVaultBtn.menuItemExisting=Open Existing Vault...
+main.vaultlist.addVaultBtn.menuItemRecover=Recover Existing Vault...
 main.vaultlist.showEventsButton.tooltip=Open event view
 ##Notificaition
 main.notification.updateAvailable=Update is available.
@@ -534,6 +535,14 @@ recoveryKey.recover.resetVaultConfigSuccess.message=Vault config reset successfu
 recoveryKey.recover.resetMasterkeyFileSuccess.message=Masterkey file reset successful
 
 ### Recover Kram
+recoveryKey.recoverExisting.title=Vault Added
+recoveryKey.recoverExisting.message=Recovery Vault added
+recoveryKey.recoverExisting.description=Your Vault added successfully.
+
+recoveryKey.alreadyExists.title=Vault Already Exists
+recoveryKey.alreadyExists.message=Vault already exists in VaultList.
+recoveryKey.alreadyExists.description=Nothing happend.
+
 
 recoveryKey.noDDirDetected.title=Invalid Selection
 recoveryKey.noDDirDetected.description=The selected folder must contain a subfolder named "d".