recover button now in VaultListController

This commit is contained in:
Jan-Peter Klein
2025-06-30 17:36:30 +02:00
parent ad214691f9
commit edc308ccd1
8 changed files with 141 additions and 86 deletions

View File

@@ -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 {

View File

@@ -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();

View File

@@ -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"), //

View File

@@ -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();
}
})

View File

@@ -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())) {