Parcourir la source

Merge pull request #3082 from cryptomator/feature/add-vault-button-to-dropdown

UI Enhancement: Improved 'Add Vault' Button Functionality
mindmonk il y a 1 an
Parent
commit
0e52b7aff4

+ 1 - 14
src/main/java/org/cryptomator/ui/addvaultwizard/AddVaultModule.java

@@ -45,9 +45,8 @@ public abstract class AddVaultModule {
 	@Provides
 	@AddVaultWizardWindow
 	@AddVaultWizardScoped
-	static Stage provideStage(StageFactory factory, @PrimaryStage Stage primaryStage, ResourceBundle resourceBundle) {
+	static Stage provideStage(StageFactory factory, @PrimaryStage Stage primaryStage) {
 		Stage stage = factory.create();
-		stage.setTitle(resourceBundle.getString("addvaultwizard.title"));
 		stage.setResizable(false);
 		stage.initModality(Modality.WINDOW_MODAL);
 		stage.initOwner(primaryStage);
@@ -90,13 +89,6 @@ public abstract class AddVaultModule {
 
 	// ------------------
 
-	@Provides
-	@FxmlScene(FxmlFile.ADDVAULT_WELCOME)
-	@AddVaultWizardScoped
-	static Scene provideWelcomeScene(@AddVaultWizardWindow FxmlLoaderFactory fxmlLoaders) {
-		return fxmlLoaders.createScene(FxmlFile.ADDVAULT_WELCOME);
-	}
-
 	@Provides
 	@FxmlScene(FxmlFile.ADDVAULT_EXISTING)
 	@AddVaultWizardScoped
@@ -148,11 +140,6 @@ public abstract class AddVaultModule {
 
 	// ------------------
 
-	@Binds
-	@IntoMap
-	@FxControllerKey(AddVaultWelcomeController.class)
-	abstract FxController bindWelcomeController(AddVaultWelcomeController controller);
-
 	@Binds
 	@IntoMap
 	@FxControllerKey(ChooseExistingVaultController.class)

+ 0 - 38
src/main/java/org/cryptomator/ui/addvaultwizard/AddVaultWelcomeController.java

@@ -1,38 +0,0 @@
-package org.cryptomator.ui.addvaultwizard;
-
-import dagger.Lazy;
-import org.cryptomator.ui.common.FxController;
-import org.cryptomator.ui.common.FxmlFile;
-import org.cryptomator.ui.common.FxmlScene;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.inject.Inject;
-import javafx.scene.Scene;
-import javafx.stage.Stage;
-
-@AddVaultWizardScoped
-public class AddVaultWelcomeController implements FxController {
-
-	private static final Logger LOG = LoggerFactory.getLogger(AddVaultWelcomeController.class);
-	private final Stage window;
-	private final Lazy<Scene> chooseExistingVaultScene;
-	private final Lazy<Scene> createNewVaultScene;
-
-	@Inject
-	AddVaultWelcomeController(@AddVaultWizardWindow Stage window, @FxmlScene(FxmlFile.ADDVAULT_EXISTING) Lazy<Scene> chooseExistingVaultScene, @FxmlScene(FxmlFile.ADDVAULT_NEW_NAME) Lazy<Scene> createNewVaultScene) {
-		this.window = window;
-		this.chooseExistingVaultScene = chooseExistingVaultScene;
-		this.createNewVaultScene = createNewVaultScene;
-	}
-
-	public void createNewVault() {
-		LOG.debug("AddVaultWelcomeController.createNewVault()");
-		window.setScene(createNewVaultScene.get());
-	}
-
-	public void chooseExistingVault() {
-		LOG.debug("AddVaultWelcomeController.chooseExistingVault()");
-		window.setScene(chooseExistingVaultScene.get());
-	}
-}

+ 16 - 4
src/main/java/org/cryptomator/ui/addvaultwizard/AddVaultWizardComponent.java

@@ -12,6 +12,7 @@ import org.cryptomator.ui.common.FxmlScene;
 
 import javafx.scene.Scene;
 import javafx.stage.Stage;
+import java.util.ResourceBundle;
 
 @AddVaultWizardScoped
 @Subcomponent(modules = {AddVaultModule.class})
@@ -20,12 +21,23 @@ public interface AddVaultWizardComponent {
 	@AddVaultWizardWindow
 	Stage window();
 
-	@FxmlScene(FxmlFile.ADDVAULT_WELCOME)
-	Lazy<Scene> scene();
+	@FxmlScene(FxmlFile.ADDVAULT_NEW_NAME)
+	Lazy<Scene> sceneNew();
+	@FxmlScene(FxmlFile.ADDVAULT_EXISTING)
+	Lazy<Scene> sceneExisting();
 
-	default void showAddVaultWizard() {
+	default void showAddNewVaultWizard(ResourceBundle resourceBundle) {
 		Stage stage = window();
-		stage.setScene(scene().get());
+		stage.setScene(sceneNew().get());
+		stage.setTitle(resourceBundle.getString("addvaultwizard.new.title"));
+		stage.sizeToScene();
+		stage.show();
+	}
+
+	default void showAddExistingVaultWizard(ResourceBundle resourceBundle) {
+		Stage stage = window();
+		stage.setScene(sceneExisting().get());
+		stage.setTitle(resourceBundle.getString("addvaultwizard.existing.title"));
 		stage.sizeToScene();
 		stage.show();
 	}

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

@@ -35,7 +35,6 @@ public class ChooseExistingVaultController implements FxController {
 	private static final Logger LOG = LoggerFactory.getLogger(ChooseExistingVaultController.class);
 
 	private final Stage window;
-	private final Lazy<Scene> welcomeScene;
 	private final Lazy<Scene> successScene;
 	private final FxApplicationWindows appWindows;
 	private final ObjectProperty<Path> vaultPath;
@@ -45,9 +44,15 @@ public class ChooseExistingVaultController implements FxController {
 	private final ObservableValue<Image> screenshot;
 
 	@Inject
-	ChooseExistingVaultController(@AddVaultWizardWindow Stage window, @FxmlScene(FxmlFile.ADDVAULT_WELCOME) Lazy<Scene> welcomeScene, @FxmlScene(FxmlFile.ADDVAULT_SUCCESS) Lazy<Scene> successScene, FxApplicationWindows appWindows, ObjectProperty<Path> vaultPath, @AddVaultWizardWindow ObjectProperty<Vault> vault, VaultListManager vaultListManager, ResourceBundle resourceBundle, FxApplicationStyle applicationStyle) {
+	ChooseExistingVaultController(@AddVaultWizardWindow Stage window, //
+								  @FxmlScene(FxmlFile.ADDVAULT_SUCCESS) Lazy<Scene> successScene, //
+								  FxApplicationWindows appWindows, //
+								  ObjectProperty<Path> vaultPath, //
+								  @AddVaultWizardWindow ObjectProperty<Vault> vault, //
+								  VaultListManager vaultListManager, //
+								  ResourceBundle resourceBundle, //
+								  FxApplicationStyle applicationStyle) {
 		this.window = window;
-		this.welcomeScene = welcomeScene;
 		this.successScene = successScene;
 		this.appWindows = appWindows;
 		this.vaultPath = vaultPath;
@@ -70,11 +75,6 @@ public class ChooseExistingVaultController implements FxController {
 		return new Image((Objects.requireNonNull(getClass().getResource(imageResourcePath)).toString()));
 	}
 
-	@FXML
-	public void back() {
-		window.setScene(welcomeScene.get());
-	}
-
 	@FXML
 	public void chooseFileAndNext() {
 		FileChooser fileChooser = new FileChooser();

+ 4 - 9
src/main/java/org/cryptomator/ui/addvaultwizard/CreateNewVaultNameController.java

@@ -17,7 +17,6 @@ import javafx.scene.Scene;
 import javafx.scene.control.TextField;
 import javafx.stage.Stage;
 import java.nio.file.Path;
-import java.util.ResourceBundle;
 import java.util.regex.Pattern;
 
 @AddVaultWizardScoped
@@ -27,16 +26,17 @@ public class CreateNewVaultNameController implements FxController {
 
 	public TextField textField;
 	private final Stage window;
-	private final Lazy<Scene> welcomeScene;
 	private final Lazy<Scene> chooseLocationScene;
 	private final ObjectProperty<Path> vaultPath;
 	private final StringProperty vaultName;
 	private final BooleanBinding validVaultName;
 
 	@Inject
-	CreateNewVaultNameController(@AddVaultWizardWindow Stage window, @FxmlScene(FxmlFile.ADDVAULT_WELCOME) Lazy<Scene> welcomeScene, @FxmlScene(FxmlFile.ADDVAULT_NEW_LOCATION) Lazy<Scene> chooseLocationScene, ObjectProperty<Path> vaultPath, @Named("vaultName") StringProperty vaultName, ResourceBundle resourceBundle) {
+	CreateNewVaultNameController(@AddVaultWizardWindow Stage window, //
+								 @FxmlScene(FxmlFile.ADDVAULT_NEW_LOCATION) Lazy<Scene> chooseLocationScene, //
+								 ObjectProperty<Path> vaultPath, //
+								 @Named("vaultName") StringProperty vaultName) {
 		this.window = window;
-		this.welcomeScene = welcomeScene;
 		this.chooseLocationScene = chooseLocationScene;
 		this.vaultPath = vaultPath;
 		this.vaultName = vaultName;
@@ -58,11 +58,6 @@ public class CreateNewVaultNameController implements FxController {
 		}
 	}
 
-	@FXML
-	public void back() {
-		window.setScene(welcomeScene.get());
-	}
-
 	@FXML
 	public void next() {
 		window.setScene(chooseLocationScene.get());

+ 0 - 1
src/main/java/org/cryptomator/ui/common/FxmlFile.java

@@ -8,7 +8,6 @@ public enum FxmlFile {
 	ADDVAULT_NEW_PASSWORD("/fxml/addvault_new_password.fxml"), //
 	ADDVAULT_NEW_RECOVERYKEY("/fxml/addvault_new_recoverykey.fxml"), //
 	ADDVAULT_SUCCESS("/fxml/addvault_success.fxml"), //
-	ADDVAULT_WELCOME("/fxml/addvault_welcome.fxml"), //
 	CHANGEPASSWORD("/fxml/changepassword.fxml"), //
 	CONVERTVAULT_HUBTOPASSWORD_START("/fxml/convertvault_hubtopassword_start.fxml"), //
 	CONVERTVAULT_HUBTOPASSWORD_CONVERT("/fxml/convertvault_hubtopassword_convert.fxml"), //

+ 3 - 1
src/main/java/org/cryptomator/ui/mainwindow/MainWindowSceneFactory.java

@@ -16,6 +16,7 @@ import javafx.stage.Stage;
 public class MainWindowSceneFactory extends DefaultSceneFactory {
 
 	protected static final KeyCodeCombination SHORTCUT_N = new KeyCodeCombination(KeyCode.N, KeyCombination.SHORTCUT_DOWN);
+	protected static final KeyCodeCombination SHORTCUT_O = new KeyCodeCombination(KeyCode.O, KeyCombination.SHORTCUT_DOWN);
 
 	private final Lazy<MainWindowTitleController> mainWindowTitleController;
 	private final Lazy<VaultListController> vaultListController;
@@ -34,6 +35,7 @@ public class MainWindowSceneFactory extends DefaultSceneFactory {
 		} else {
 			scene.getAccelerators().put(SHORTCUT_W, mainWindowTitleController.get()::close);
 		}
-		scene.getAccelerators().put(SHORTCUT_N, vaultListController.get()::didClickAddVault);
+		scene.getAccelerators().put(SHORTCUT_N, vaultListController.get()::didClickAddNewVault);
+		scene.getAccelerators().put(SHORTCUT_O, vaultListController.get()::didClickAddExistingVault);
 	}
 }

+ 30 - 3
src/main/java/org/cryptomator/ui/mainwindow/VaultListController.java

@@ -20,7 +20,9 @@ import javafx.beans.property.SimpleBooleanProperty;
 import javafx.beans.value.ObservableValue;
 import javafx.collections.ListChangeListener;
 import javafx.collections.ObservableList;
+import javafx.event.Event;
 import javafx.fxml.FXML;
+import javafx.scene.control.Button;
 import javafx.scene.control.ListView;
 import javafx.scene.input.ContextMenuEvent;
 import javafx.scene.input.DragEvent;
@@ -34,6 +36,7 @@ import java.io.File;
 import java.io.IOException;
 import java.nio.file.Path;
 import java.util.EnumSet;
+import java.util.ResourceBundle;
 import java.util.Set;
 import java.util.stream.Collectors;
 
@@ -59,12 +62,21 @@ public class VaultListController implements FxController {
 	private final RemoveVaultComponent.Builder removeVaultDialogue;
 	private final VaultListManager vaultListManager;
 	private final BooleanProperty draggingVaultOver = new SimpleBooleanProperty();
+	private final ResourceBundle resourceBundle;
 
 	public ListView<Vault> vaultList;
 	public StackPane root;
+	public Button addVaultBtn;
 
 	@Inject
-	VaultListController(@MainWindow Stage mainWindow, ObservableList<Vault> vaults, ObjectProperty<Vault> selectedVault, VaultListCellFactory cellFactory, AddVaultWizardComponent.Builder addVaultWizard, RemoveVaultComponent.Builder removeVaultDialogue, VaultListManager vaultListManager) {
+	VaultListController(@MainWindow Stage mainWindow, //
+						ObservableList<Vault> vaults, //
+						ObjectProperty<Vault> selectedVault, //
+						VaultListCellFactory cellFactory, //
+						AddVaultWizardComponent.Builder addVaultWizard, //
+						RemoveVaultComponent.Builder removeVaultDialogue, //
+						VaultListManager vaultListManager, //
+						ResourceBundle resourceBundle) {
 		this.mainWindow = mainWindow;
 		this.vaults = vaults;
 		this.selectedVault = selectedVault;
@@ -72,6 +84,7 @@ public class VaultListController implements FxController {
 		this.addVaultWizard = addVaultWizard;
 		this.removeVaultDialogue = removeVaultDialogue;
 		this.vaultListManager = vaultListManager;
+		this.resourceBundle = resourceBundle;
 
 		this.emptyVaultList = Bindings.isEmpty(vaults);
 
@@ -127,6 +140,15 @@ public class VaultListController implements FxController {
 		root.setOnDragOver(this::handleDragEvent);
 		root.setOnDragDropped(this::handleDragEvent);
 		root.setOnDragExited(this::handleDragEvent);
+
+		addVaultBtn.addEventFilter(ContextMenuEvent.CONTEXT_MENU_REQUESTED, Event::consume);
+	}
+
+	@FXML
+	private void showMenu() {
+		double screenX = addVaultBtn.localToScreen(addVaultBtn.getBoundsInLocal()).getMinX();
+		double screenY = addVaultBtn.localToScreen(addVaultBtn.getBoundsInLocal()).getMaxY();
+		addVaultBtn.getContextMenu().show(addVaultBtn, screenX, screenY);
 	}
 
 	private void deselect(MouseEvent released) {
@@ -144,8 +166,13 @@ public class VaultListController implements FxController {
 	}
 
 	@FXML
-	public void didClickAddVault() {
-		addVaultWizard.build().showAddVaultWizard();
+	public void didClickAddNewVault() {
+		addVaultWizard.build().showAddNewVaultWizard(resourceBundle);
+	}
+
+	@FXML
+	public void didClickAddExistingVault() {
+		addVaultWizard.build().showAddExistingVaultWizard(resourceBundle);
 	}
 
 	private void pressedShortcutToRemoveVault() {

+ 10 - 0
src/main/resources/css/dark_theme.css

@@ -795,6 +795,16 @@
 	-fx-scale-shape: false;
 }
 
+/*******************************************************************************
+ *                                                                             *
+ * Add Vault - MenuItem                                                                    *
+ *                                                                             *
+ ******************************************************************************/
+
+.add-vault-menu-item {
+    -fx-padding: 4px 8px;
+}
+
 /*******************************************************************************
  *                                                                             *
  * ProgressBar                                                                 *

+ 10 - 0
src/main/resources/css/light_theme.css

@@ -794,6 +794,16 @@
 	-fx-scale-shape: false;
 }
 
+/*******************************************************************************
+ *                                                                             *
+ * Add Vault - MenuItem                                                                    *
+ *                                                                             *
+ ******************************************************************************/
+
+.add-vault-menu-item {
+    -fx-padding: 4px 8px;
+}
+
 /*******************************************************************************
  *                                                                             *
  * ProgressBar                                                                 *

+ 1 - 2
src/main/resources/fxml/addvault_existing.fxml

@@ -24,9 +24,8 @@
 
 		<Region VBox.vgrow="ALWAYS"/>
 
-		<ButtonBar buttonMinWidth="120" buttonOrder="B+X">
+		<ButtonBar buttonMinWidth="120" buttonOrder="+X">
 			<buttons>
-				<Button text="%generic.button.back" ButtonBar.buttonData="BACK_PREVIOUS" onAction="#back"/>
 				<Button fx:id="finishButton" text="%addvaultwizard.existing.chooseBtn" ButtonBar.buttonData="NEXT_FORWARD" onAction="#chooseFileAndNext" defaultButton="true"/>
 			</buttons>
 		</ButtonBar>

+ 1 - 2
src/main/resources/fxml/addvault_new_name.fxml

@@ -68,9 +68,8 @@
 
 		<Region VBox.vgrow="ALWAYS"/>
 
-		<ButtonBar buttonMinWidth="120" buttonOrder="B+X">
+		<ButtonBar buttonMinWidth="120" buttonOrder="+X">
 			<buttons>
-				<Button text="%generic.button.back" ButtonBar.buttonData="BACK_PREVIOUS" onAction="#back"/>
 				<Button text="%generic.button.next" ButtonBar.buttonData="NEXT_FORWARD" onAction="#next" defaultButton="true" disable="${!controller.validVaultName}"/>
 			</buttons>
 		</ButtonBar>

+ 0 - 44
src/main/resources/fxml/addvault_welcome.fxml

@@ -1,44 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<?import org.cryptomator.ui.controls.FontAwesome5IconView?>
-<?import javafx.geometry.Insets?>
-<?import javafx.scene.control.Button?>
-<?import javafx.scene.image.Image?>
-<?import javafx.scene.image.ImageView?>
-<?import javafx.scene.layout.Region?>
-<?import javafx.scene.layout.VBox?>
-<VBox xmlns:fx="http://javafx.com/fxml"
-	  xmlns="http://javafx.com/javafx"
-	  fx:controller="org.cryptomator.ui.addvaultwizard.AddVaultWelcomeController"
-	  prefWidth="450"
-	  prefHeight="450"
-	  spacing="12"
-	  alignment="TOP_CENTER">
-	<padding>
-		<Insets topRightBottomLeft="24"/>
-	</padding>
-	<children>
-		<Region VBox.vgrow="ALWAYS"/>
-
-		<ImageView VBox.vgrow="ALWAYS" fitHeight="128" preserveRatio="true" smooth="true" cache="true">
-			<Image url="@../img/logo.png"/>
-		</ImageView>
-
-		<Region VBox.vgrow="ALWAYS"/>
-
-		<VBox alignment="CENTER" spacing="9">
-			<Button styleClass="button-large" text="%addvaultwizard.welcome.newButton" onAction="#createNewVault" prefWidth="Infinity">
-				<graphic>
-					<FontAwesome5IconView glyph="MAGIC" glyphSize="15"/>
-				</graphic>
-			</Button>
-			<Button styleClass="button-large" text="%addvaultwizard.welcome.existingButton" onAction="#chooseExistingVault" prefWidth="Infinity">
-				<graphic>
-					<FontAwesome5IconView glyph="FOLDER_OPEN" glyphSize="15"/>
-				</graphic>
-			</Button>
-		</VBox>
-
-		<Region VBox.vgrow="ALWAYS"/>
-	</children>
-</VBox>

+ 20 - 2
src/main/resources/fxml/vault_list.fxml

@@ -8,6 +8,8 @@
 <?import javafx.scene.layout.StackPane?>
 <?import javafx.scene.layout.VBox?>
 <?import javafx.scene.shape.Arc?>
+<?import javafx.scene.control.ContextMenu?>
+<?import javafx.scene.control.MenuItem?>
 <StackPane xmlns:fx="http://javafx.com/fxml"
 		   xmlns="http://javafx.com/javafx"
 		   fx:id="root"
@@ -26,10 +28,26 @@
 				<Arc VBox.vgrow="NEVER" styleClass="onboarding-overlay-arc" type="OPEN" centerX="50" centerY="0" radiusY="100" radiusX="50" startAngle="0" length="-60" strokeWidth="1"/>
 			</VBox>
 		</StackPane>
-		<Button styleClass="toolbar-button" text="%main.vaultlist.addVaultBtn" onAction="#didClickAddVault" alignment="BASELINE_CENTER" maxWidth="Infinity">
+		<Button fx:id="addVaultBtn" onAction="#showMenu" styleClass="toolbar-button" text="%main.vaultlist.addVaultBtn" alignment="BASELINE_CENTER" maxWidth="Infinity" contentDisplay="RIGHT">
 			<graphic>
-				<FontAwesome5IconView glyph="PLUS"/>
+				<FontAwesome5IconView glyph="CARET_DOWN"/>
 			</graphic>
+			<contextMenu>
+				<ContextMenu>
+					<items>
+						<MenuItem styleClass="add-vault-menu-item" text="%main.vaultlist.addVaultBtn.menuItemNew" onAction="#didClickAddNewVault" >
+							<graphic>
+								<FontAwesome5IconView glyph="PLUS" textAlignment="CENTER" wrappingWidth="14" />
+							</graphic>
+						</MenuItem>
+						<MenuItem styleClass="add-vault-menu-item" text="%main.vaultlist.addVaultBtn.menuItemExisting" onAction="#didClickAddExistingVault" >
+							<graphic>
+								<FontAwesome5IconView glyph="FOLDER_OPEN" textAlignment="CENTER" wrappingWidth="14" />
+							</graphic>
+						</MenuItem>
+					</items>
+				</ContextMenu>
+			</contextMenu>
 		</Button>
 	</VBox>
 	<Region styleClass="drag-n-drop-border" visible="${controller.draggingVaultOver}"/>

+ 5 - 4
src/main/resources/i18n/strings.properties

@@ -41,10 +41,8 @@ traymenu.vault.reveal=Reveal
 
 # Add Vault Wizard
 addvaultwizard.title=Add Vault
-## Welcome
-addvaultwizard.welcome.newButton=Create New Vault
-addvaultwizard.welcome.existingButton=Open Existing Vault
 ## New
+addvaultwizard.new.title=Add New Vault
 ### Name
 addvaultwizard.new.nameInstruction=Choose a name for the vault
 addvaultwizard.new.namePrompt=Vault Name
@@ -94,6 +92,7 @@ addvault.new.readme.accessLocation.2=This is your vault's access location.
 addvault.new.readme.accessLocation.3=Any files added to this volume will be encrypted by Cryptomator. You can work on it like on any other drive/folder. This is only a decrypted view of its content, your files stay encrypted on your hard drive all the time.
 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.
 addvaultwizard.existing.chooseBtn=Choose…
 addvaultwizard.existing.filePickerTitle=Select Vault File
@@ -367,7 +366,9 @@ main.vaultlist.contextMenu.unlock=Unlock…
 main.vaultlist.contextMenu.unlockNow=Unlock Now
 main.vaultlist.contextMenu.vaultoptions=Show Vault Options
 main.vaultlist.contextMenu.reveal=Reveal Drive
-main.vaultlist.addVaultBtn=Add Vault
+main.vaultlist.addVaultBtn=Add
+main.vaultlist.addVaultBtn.menuItemNew=New Vault...
+main.vaultlist.addVaultBtn.menuItemExisting=Existing Vault...
 ## Vault Detail
 ### Welcome
 main.vaultDetail.welcomeOnboarding=Thanks for choosing Cryptomator to protect your files. If you need any assistance, check out our getting started guides: