Просмотр исходного кода

dialogs with icons and some other ui improvements

Jan-Peter Klein 1 неделя назад
Родитель
Сommit
e78a064af6

+ 2 - 1
src/main/java/org/cryptomator/ui/keyloading/masterkeyfile/ChooseMasterkeyFileController.java

@@ -77,8 +77,9 @@ public class ChooseMasterkeyFileController implements FxController {
 
 	@FXML
 	void restoreMasterkey() {
+		Stage ownerStage = (Stage) window.getOwner();
 		window.close();
-		recoveryKeyWindow.create(vault, window, new SimpleObjectProperty<>(RecoveryActionType.RESTORE_MASTERKEY)).showOnboardingDialogWindow();
+		recoveryKeyWindow.create(vault, ownerStage, new SimpleObjectProperty<>(RecoveryActionType.RESTORE_MASTERKEY)).showOnboardingDialogWindow();
 	}
 
 	@FXML

+ 1 - 1
src/main/java/org/cryptomator/ui/recoverykey/RecoveryKeyExpertSettingsController.java

@@ -27,7 +27,7 @@ public class RecoveryKeyExpertSettingsController implements FxController {
 
 	public static final int MAX_SHORTENING_THRESHOLD = 220;
 	public static final int MIN_SHORTENING_THRESHOLD = 36;
-	private static final String DOCS_NAME_SHORTENING_URL = "https://docs.cryptomator.org/security/architecture/#name-shortening";
+	private static final String DOCS_NAME_SHORTENING_URL = "https://docs.cryptomator.org/security/vault/#name-shortening";
 
 	private final Stage window;
 	private final Lazy<Application> application;

+ 52 - 36
src/main/java/org/cryptomator/ui/recoverykey/RecoveryKeyOnboardingController.java

@@ -8,16 +8,19 @@ import org.cryptomator.ui.common.FxmlScene;
 
 import javax.inject.Inject;
 import javax.inject.Named;
-import javafx.beans.property.BooleanProperty;
+import javafx.beans.binding.Bindings;
+import javafx.beans.binding.BooleanBinding;
 import javafx.beans.property.ObjectProperty;
-import javafx.beans.property.SimpleBooleanProperty;
 import javafx.fxml.FXML;
 import javafx.scene.Scene;
 import javafx.scene.control.Button;
 import javafx.scene.control.CheckBox;
 import javafx.scene.control.Label;
 import javafx.scene.control.RadioButton;
+import javafx.scene.control.Toggle;
 import javafx.scene.control.ToggleGroup;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.Region;
 import javafx.scene.layout.VBox;
 import javafx.stage.Stage;
 import java.util.ResourceBundle;
@@ -48,8 +51,10 @@ public class RecoveryKeyOnboardingController implements FxController {
 	private Button nextButton;
 	@FXML
 	private VBox chooseMethodeBox;
-	private final ToggleGroup methodToggleGroup = new ToggleGroup();
-	private final BooleanProperty showThirdText = new SimpleBooleanProperty(true);
+	@FXML
+	private ToggleGroup methodToggleGroup = new ToggleGroup();
+	@FXML
+	private HBox hBox;
 
 	@Inject
 	public RecoveryKeyOnboardingController(@RecoveryKeyWindow Stage window, //
@@ -68,38 +73,57 @@ public class RecoveryKeyOnboardingController implements FxController {
 
 	@FXML
 	public void initialize() {
-
 		recoveryKeyRadio.setToggleGroup(methodToggleGroup);
 		passwordRadio.setToggleGroup(methodToggleGroup);
 
-		boolean showMethodSelection = (recoverType.get() == RecoveryActionType.RESTORE_VAULT_CONFIG);
-		chooseMethodeBox.setVisible(showMethodSelection);
-		chooseMethodeBox.setManaged(showMethodSelection);
+		BooleanBinding showMethodSelection = Bindings.createBooleanBinding(
+				() -> recoverType.get() == RecoveryActionType.RESTORE_VAULT_CONFIG, recoverType);
+		chooseMethodeBox.visibleProperty().bind(showMethodSelection);
+		chooseMethodeBox.managedProperty().bind(showMethodSelection);
 
-		nextButton.disableProperty().bind( //
-				affirmationBox.selectedProperty().not() //
-						.or(methodToggleGroup.selectedToggleProperty().isNull() //
-								.and(showMethodSelectionProperty())));
+		nextButton.disableProperty().bind(
+				affirmationBox.selectedProperty().not()
+						.or(methodToggleGroup.selectedToggleProperty().isNull().and(showMethodSelection))
+		);
 
 		switch (recoverType.get()) {
-			case RESTORE_VAULT_CONFIG -> {
-				window.setTitle(resourceBundle.getString("recoveryKey.recoverVaultConfig.title"));
-				messageLabel.setText(resourceBundle.getString("recoveryKey.recover.onBoarding.readThis"));
-				secondTextDesc.setText(resourceBundle.getString("recoveryKey.recover.onBoarding.recoverVaultConfig.intro2"));
-				showThirdText.set(false);
-			}
-			case RESTORE_MASTERKEY -> {
-				window.setTitle(resourceBundle.getString("recoveryKey.recoverMasterkey.title"));
-				messageLabel.setText(resourceBundle.getString("recoveryKey.recover.onBoarding.readThis"));
-				titleLabel.setText(resourceBundle.getString("recoveryKey.recoverMasterkey.title"));
-				secondTextDesc.setText(resourceBundle.getString("recoveryKey.recover.onBoarding.recoverMasterkey.intro2"));
-				showThirdText.set(false);
-			}
+			case RESTORE_MASTERKEY ->
+					window.setTitle(resourceBundle.getString("recoveryKey.recoverMasterkey.title"));
+			case RESTORE_ALL, RESTORE_VAULT_CONFIG ->
+					window.setTitle(resourceBundle.getString("recoveryKey.recoverVaultConfig.title"));
+			default -> window.setTitle("");
 		}
-	}
 
-	private BooleanProperty showMethodSelectionProperty() {
-		return new SimpleBooleanProperty(recoverType.get() == RecoveryActionType.RESTORE_VAULT_CONFIG);
+		messageLabel.textProperty().bind(Bindings.createStringBinding(
+				() -> resourceBundle.getString("recoveryKey.recover.onBoarding.readThis"), recoverType));
+
+		titleLabel.textProperty().bind(Bindings.createStringBinding(() ->
+				recoverType.get() == RecoveryActionType.RESTORE_MASTERKEY
+						? resourceBundle.getString("recoveryKey.recoverMasterkey.title")
+						: resourceBundle.getString("recoveryKey.recoverVaultConfig.title"), recoverType));
+
+		BooleanBinding isMaster = Bindings.createBooleanBinding(
+				() -> recoverType.get() == RecoveryActionType.RESTORE_MASTERKEY, recoverType);
+		hBox.minHeightProperty().bind(Bindings.when(isMaster).then(206.0).otherwise(Region.USE_COMPUTED_SIZE));
+
+		secondTextDesc.textProperty().bind(Bindings.createStringBinding(() -> {
+			RecoveryActionType type = recoverType.get();
+			Toggle sel = methodToggleGroup.getSelectedToggle();
+			return switch (type) {
+				case RESTORE_VAULT_CONFIG -> resourceBundle.getString(sel == passwordRadio
+						? "recoveryKey.recover.onBoarding.recoverVaultConfig.intro2.password"
+						: "recoveryKey.recover.onBoarding.recoverVaultConfig.intro2.recoveryKey");
+				case RESTORE_MASTERKEY -> resourceBundle.getString("recoveryKey.recover.onBoarding.recoverMasterkey.intro2");
+				case RESTORE_ALL       -> resourceBundle.getString("recoveryKey.recover.onBoarding.recoverVaultConfig.intro2.recoveryKey");
+				default                -> "";
+			};
+		}, recoverType, methodToggleGroup.selectedToggleProperty()));
+
+		showMethodSelection.addListener((_, _, nowShown) -> {
+			if (nowShown && methodToggleGroup.getSelectedToggle() == null) {
+				methodToggleGroup.selectToggle(recoveryKeyRadio);
+			}
+		});
 	}
 
 	@FXML
@@ -127,13 +151,5 @@ public class RecoveryKeyOnboardingController implements FxController {
 		window.centerOnScreen();
 	}
 
-	public BooleanProperty showThirdTextProperty() {
-		return showThirdText;
-	}
-
-	public boolean getShowThirdText() {
-		return showThirdText.get();
-	}
-
 }
 

+ 31 - 15
src/main/resources/fxml/convertvault_hubtopassword_convert.fxml

@@ -6,7 +6,12 @@
 <?import javafx.scene.control.ButtonBar?>
 <?import javafx.scene.layout.Region?>
 <?import javafx.scene.layout.VBox?>
-<VBox xmlns:fx="http://javafx.com/fxml"
+<?import javafx.scene.layout.HBox?>
+<?import javafx.scene.layout.StackPane?>
+<?import org.cryptomator.ui.controls.FontAwesome5IconView?>
+<?import javafx.scene.shape.Circle?>
+<?import javafx.scene.Group?>
+<HBox xmlns:fx="http://javafx.com/fxml"
 	  xmlns="http://javafx.com/javafx"
 	  fx:controller="org.cryptomator.ui.convertvault.HubToPasswordConvertController"
 	  minWidth="400"
@@ -18,21 +23,32 @@
 		<Insets topRightBottomLeft="12"/>
 	</padding>
 	<children>
-		<fx:include fx:id="newPassword" source="new_password.fxml"/>
+		<Group>
+			<StackPane>
+				<padding>
+					<Insets topRightBottomLeft="6"/>
+				</padding>
+				<Circle styleClass="glyph-icon-primary" radius="24"/>
+				<FontAwesome5IconView styleClass="glyph-icon-white" glyph="KEY" glyphSize="24"/>
+			</StackPane>
+		</Group>
+			<VBox spacing="12" HBox.hgrow="ALWAYS" alignment="TOP_CENTER">
+			<fx:include fx:id="newPassword" source="new_password.fxml"/>
 
-		<Region VBox.vgrow="ALWAYS"/>
+			<Region VBox.vgrow="ALWAYS"/>
 
-		<VBox alignment="BOTTOM_CENTER" VBox.vgrow="ALWAYS">
-			<ButtonBar buttonMinWidth="120" buttonOrder="+CI">
-				<buttons>
-					<Button text="%generic.button.cancel" ButtonBar.buttonData="CANCEL_CLOSE" cancelButton="true" onAction="#close"/>
-					<Button fx:id="convertBtn" ButtonBar.buttonData="FINISH" defaultButton="true" onAction="#convert"> <!-- for button logic, see controller -->
-						<graphic>
-							<FontAwesome5Spinner glyphSize="12"/>
-						</graphic>
-					</Button>
-				</buttons>
-			</ButtonBar>
+			<VBox alignment="BOTTOM_CENTER" VBox.vgrow="ALWAYS">
+				<ButtonBar buttonMinWidth="120" buttonOrder="+CI">
+					<buttons>
+						<Button text="%generic.button.cancel" ButtonBar.buttonData="CANCEL_CLOSE" cancelButton="true" onAction="#close"/>
+						<Button fx:id="convertBtn" ButtonBar.buttonData="FINISH" defaultButton="true" onAction="#convert"> <!-- for button logic, see controller -->
+							<graphic>
+								<FontAwesome5Spinner glyphSize="12"/>
+							</graphic>
+						</Button>
+					</buttons>
+				</ButtonBar>
+			</VBox>
 		</VBox>
 	</children>
-</VBox>
+</HBox>

+ 24 - 14
src/main/resources/fxml/convertvault_hubtopassword_start.fxml

@@ -5,29 +5,39 @@
 <?import javafx.geometry.Insets?>
 <?import javafx.scene.control.ButtonBar?>
 <?import javafx.scene.control.Button?>
-<VBox xmlns:fx="http://javafx.com/fxml"
+<?import org.cryptomator.ui.controls.FontAwesome5IconView?>
+<?import javafx.scene.shape.Circle?>
+<?import javafx.scene.Group?>
+<HBox xmlns:fx="http://javafx.com/fxml"
 	  xmlns="http://javafx.com/javafx"
 	  fx:controller="org.cryptomator.ui.convertvault.HubToPasswordStartController"
 	  minWidth="400"
 	  maxWidth="400"
 	  minHeight="145"
-	  spacing="12"
-	  alignment="TOP_CENTER">
+	  spacing="12">
 	<padding>
 		<Insets topRightBottomLeft="12"/>
 	</padding>
-	<children>
+	<Group>
+		<StackPane>
+			<padding>
+				<Insets topRightBottomLeft="6"/>
+			</padding>
+			<Circle styleClass="glyph-icon-primary" radius="24"/>
+			<FontAwesome5IconView styleClass="glyph-icon-white" glyph="SYNC" glyphSize="24"/>
+		</StackPane>
+	</Group>
+
+	<VBox spacing="12" HBox.hgrow="ALWAYS" alignment="TOP_CENTER">
 		<fx:include fx:id="recoveryKeyValidate" source="recoverykey_validate.fxml"/>
 
 		<Region VBox.vgrow="ALWAYS"/>
 
-		<VBox alignment="BOTTOM_CENTER" VBox.vgrow="ALWAYS">
-			<ButtonBar buttonMinWidth="120" buttonOrder="+CX">
-				<buttons>
-					<Button text="%generic.button.cancel" ButtonBar.buttonData="CANCEL_CLOSE" cancelButton="true" onAction="#close"/>
-					<Button text="%generic.button.next" ButtonBar.buttonData="NEXT_FORWARD" defaultButton="true" onAction="#next" disable="${!controller.validateController.recoveryKeyCorrect}"/>
-				</buttons>
-			</ButtonBar>
-		</VBox>
-	</children>
-</VBox>
+		<ButtonBar buttonMinWidth="120" buttonOrder="+CX">
+			<buttons>
+				<Button text="%generic.button.cancel" ButtonBar.buttonData="CANCEL_CLOSE" cancelButton="true" onAction="#close"/>
+				<Button text="%generic.button.next" ButtonBar.buttonData="NEXT_FORWARD" defaultButton="true" onAction="#next" disable="${!controller.validateController.recoveryKeyCorrect}"/>
+			</buttons>
+		</ButtonBar>
+	</VBox>
+</HBox>

+ 1 - 0
src/main/resources/fxml/recoverykey_expert_settings.fxml

@@ -57,6 +57,7 @@
 					</tooltip>
 				</Hyperlink>
 			</HBox>
+			<Label text="%recoveryKey.recover.expertSettings.shorteningThreshold.title" wrapText="true"/>
 			<NumericTextField fx:id="shorteningThresholdTextField"/>
 			<HBox alignment="TOP_RIGHT">
 				<Region minWidth="4" prefWidth="4" HBox.hgrow="NEVER"/>

+ 62 - 57
src/main/resources/fxml/recoverykey_onboarding.fxml

@@ -5,79 +5,84 @@
 <?import javafx.scene.control.ButtonBar?>
 <?import javafx.scene.control.CheckBox?>
 <?import javafx.scene.control.Label?>
-<?import javafx.scene.image.Image?>
+<?import javafx.scene.control.RadioButton?>
 <?import javafx.scene.control.ToggleGroup?>
-<?import javafx.scene.image.ImageView?>
 <?import javafx.scene.layout.ColumnConstraints?>
 <?import javafx.scene.layout.GridPane?>
 <?import javafx.scene.layout.HBox?>
 <?import javafx.scene.layout.Region?>
 <?import javafx.scene.layout.RowConstraints?>
+<?import javafx.scene.layout.StackPane?>
 <?import javafx.scene.layout.VBox?>
-<?import javafx.scene.control.RadioButton?>
-<VBox xmlns:fx="http://javafx.com/fxml"
+<?import javafx.scene.shape.Circle?>
+<?import org.cryptomator.ui.controls.FontAwesome5IconView?>
+
+<?import javafx.scene.Group?>
+<HBox xmlns:fx="http://javafx.com/fxml"
 	  xmlns="http://javafx.com/javafx"
+	  fx:id="hBox"
 	  fx:controller="org.cryptomator.ui.recoverykey.RecoveryKeyOnboardingController"
-	  prefWidth="650"
-	  prefHeight="400"
-	  spacing="12">
+	  prefWidth="480"
+	  minHeight="242"
+	  spacing="12"
+	  VBox.vgrow="ALWAYS"
+>
 	<padding>
 		<Insets topRightBottomLeft="12"/>
 	</padding>
-	<children>
-		<HBox VBox.vgrow="ALWAYS">
-			<VBox alignment="CENTER" minWidth="175" maxWidth="175">
-				<ImageView VBox.vgrow="ALWAYS" fitHeight="128" preserveRatio="true" cache="true">
-					<Image url="@../img/logo128.png"/>
-				</ImageView>
+	<Group>
+		<StackPane>
+			<padding>
+				<Insets topRightBottomLeft="6"/>
+			</padding>
+			<Circle styleClass="glyph-icon-primary" radius="24"/>
+			<FontAwesome5IconView styleClass="glyph-icon-white" glyph="SYNC" glyphSize="24"/>
+		</StackPane>
+	</Group>
+	<VBox HBox.hgrow="ALWAYS" spacing="12">
+		<Label fx:id="titleLabel" text="%recoveryKey.recoverVaultConfig.title" styleClass="label-extra-large"/>
+		<VBox spacing="6">
+			<VBox fx:id="chooseMethodeBox" spacing="6">
+				<Label text="%recoveryKey.recover.onBoarding.chooseMethod"/>
+				<RadioButton fx:id="recoveryKeyRadio" text="%recoveryKey.recover.onBoarding.useRecoveryKey" selected="true">
+					<toggleGroup>
+						<ToggleGroup fx:id="methodToggleGroup"/>
+					</toggleGroup>
+				</RadioButton>
+				<RadioButton fx:id="passwordRadio" text="%recoveryKey.recover.onBoarding.usePassword"/>
 			</VBox>
-			<VBox HBox.hgrow="ALWAYS" alignment="CENTER">
+
+			<Label fx:id="messageLabel" text="%recoveryKey.recover.onBoarding.message" wrapText="true"/>
+			<GridPane alignment="CENTER_LEFT">
 				<padding>
-					<Insets topRightBottomLeft="12"/>
+					<Insets left="6"/>
 				</padding>
-				<Label fx:id="titleLabel" text="%recoveryKey.recoverVaultConfig.title" styleClass="label-extra-large"/>
-				<Region minHeight="15"/>
-				<VBox>
-					<Label fx:id="messageLabel" text="%recoveryKey.recover.onBoarding.message" wrapText="true"/>
-					<GridPane alignment="CENTER_LEFT" >
-						<padding>
-							<Insets left="6"/>
-						</padding>
-						<columnConstraints>
-							<ColumnConstraints minWidth="20" halignment="LEFT"/>
-							<ColumnConstraints fillWidth="true"/>
-						</columnConstraints>
-						<rowConstraints>
-							<RowConstraints valignment="TOP"/>
-							<RowConstraints valignment="TOP"/>
-							<RowConstraints valignment="TOP"/>
-						</rowConstraints>
-						<Label text="1." GridPane.rowIndex="0" GridPane.columnIndex="0" />
-						<Label text="%recoveryKey.recover.onBoarding.intro1" wrapText="true" GridPane.rowIndex="0" GridPane.columnIndex="1" />
-						<Label text="2." GridPane.rowIndex="1" GridPane.columnIndex="0" />
-						<Label fx:id="secondTextDesc" text="%recoveryKey.recover.onBoarding.intro2" wrapText="true" GridPane.rowIndex="1" GridPane.columnIndex="1" />
-						<Label text="3." GridPane.rowIndex="2" GridPane.columnIndex="0" visible="${controller.showThirdText}" managed="${controller.showThirdText}" />
-						<Label text="%recoveryKey.recover.onBoarding.intro3" wrapText="true" GridPane.rowIndex="2" GridPane.columnIndex="1" visible="${controller.showThirdText}" managed="${controller.showThirdText}" />
-					</GridPane>
-					<Region minHeight="15"/>
-					<VBox fx:id="chooseMethodeBox">
-						<Label text="%recoveryKey.recover.onBoarding.chooseMethod"/>
-						<RadioButton fx:id="recoveryKeyRadio" text="%recoveryKey.recover.onBoarding.useRecoveryKey">
-							<toggleGroup>
-								<ToggleGroup fx:id="methodToggleGroup"/>
-							</toggleGroup>
-						</RadioButton>
-						<RadioButton fx:id="passwordRadio" text="%recoveryKey.recover.onBoarding.usePassword"/>
-					</VBox>
-					<CheckBox fx:id="affirmationBox" text="%recoveryKey.recover.onBoarding.affirmation"/>
-				</VBox>
-			</VBox>
-		</HBox>
-		<ButtonBar buttonMinWidth="120" buttonOrder="+CX">
+				<columnConstraints>
+					<ColumnConstraints minWidth="20" halignment="LEFT"/>
+					<ColumnConstraints />
+				</columnConstraints>
+				<rowConstraints>
+					<RowConstraints valignment="TOP"/>
+					<RowConstraints valignment="TOP"/>
+					<RowConstraints valignment="TOP"/>
+				</rowConstraints>
+				<Label text="1." GridPane.rowIndex="0" GridPane.columnIndex="0"/>
+				<Label text="%recoveryKey.recover.onBoarding.intro1" wrapText="true" GridPane.rowIndex="0" GridPane.columnIndex="1"/>
+				<Label text="2." GridPane.rowIndex="1" GridPane.columnIndex="0"/>
+				<Label fx:id="secondTextDesc" text="%recoveryKey.recover.onBoarding.recoverVaultConfig.intro2.recoveryKey" wrapText="true" GridPane.rowIndex="1" GridPane.columnIndex="1"/>
+			</GridPane>
+			<CheckBox fx:id="affirmationBox" text="%recoveryKey.recover.onBoarding.affirmation"/>
+		</VBox>
+
+		<Region VBox.vgrow="ALWAYS"/>
+
+		<ButtonBar buttonMinWidth="120" buttonOrder="+CX" VBox.vgrow="NEVER">
 			<buttons>
 				<Button text="%generic.button.cancel" ButtonBar.buttonData="CANCEL_CLOSE" cancelButton="true" onAction="#close"/>
-				<Button fx:id="nextButton" text="%generic.button.next" ButtonBar.buttonData="NEXT_FORWARD" disable="${!affirmationBox.selected}" defaultButton="true" onAction="#next"/>
+				<Button fx:id="nextButton" text="%generic.button.next" ButtonBar.buttonData="NEXT_FORWARD"
+						disable="${!affirmationBox.selected}" defaultButton="true" onAction="#next"/>
 			</buttons>
 		</ButtonBar>
-	</children>
-</VBox>
+
+	</VBox>
+</HBox>

+ 21 - 7
src/main/resources/fxml/recoverykey_recover.fxml

@@ -3,26 +3,40 @@
 <?import javafx.geometry.Insets?>
 <?import javafx.scene.control.Button?>
 <?import javafx.scene.control.ButtonBar?>
+<?import javafx.scene.layout.HBox?>
 <?import javafx.scene.layout.Region?>
+<?import javafx.scene.layout.StackPane?>
 <?import javafx.scene.layout.VBox?>
-<VBox xmlns:fx="http://javafx.com/fxml"
+<?import javafx.scene.shape.Circle?>
+<?import org.cryptomator.ui.controls.FontAwesome5IconView?>
+<?import javafx.scene.Group?>
+
+<HBox xmlns:fx="http://javafx.com/fxml"
 	  xmlns="http://javafx.com/javafx"
 	  fx:controller="org.cryptomator.ui.recoverykey.RecoveryKeyRecoverController"
 	  minWidth="400"
 	  maxWidth="400"
 	  minHeight="145"
-	  spacing="12"
-	  alignment="TOP_CENTER">
+	  spacing="12">
 	<padding>
 		<Insets topRightBottomLeft="12"/>
 	</padding>
 	<children>
+		<Group>
+			<StackPane>
+				<padding>
+					<Insets topRightBottomLeft="6"/>
+				</padding>
+				<Circle styleClass="glyph-icon-primary" radius="24"/>
+				<FontAwesome5IconView styleClass="glyph-icon-white" glyph="SYNC" glyphSize="24"/>
+			</StackPane>
+		</Group>
 
-		<fx:include fx:id="recoveryKeyValidate" source="recoverykey_validate.fxml"/>
+		<VBox spacing="12" HBox.hgrow="ALWAYS" alignment="TOP_CENTER">
+			<fx:include fx:id="recoveryKeyValidate" source="recoverykey_validate.fxml"/>
 
-		<Region VBox.vgrow="ALWAYS"/>
+			<Region VBox.vgrow="ALWAYS"/>
 
-		<VBox alignment="BOTTOM_CENTER" VBox.vgrow="ALWAYS">
 			<ButtonBar buttonMinWidth="120" buttonOrder="+BX">
 				<buttons>
 					<Button fx:id="cancelButton" ButtonBar.buttonData="BACK_PREVIOUS" cancelButton="true" onAction="#close"/>
@@ -31,4 +45,4 @@
 			</ButtonBar>
 		</VBox>
 	</children>
-</VBox>
+</HBox>

+ 27 - 11
src/main/resources/fxml/recoverykey_reset_password.fxml

@@ -5,7 +5,12 @@
 <?import javafx.scene.control.ButtonBar?>
 <?import javafx.scene.layout.Region?>
 <?import javafx.scene.layout.VBox?>
-<VBox xmlns:fx="http://javafx.com/fxml"
+<?import javafx.scene.layout.HBox?>
+<?import javafx.scene.layout.StackPane?>
+<?import org.cryptomator.ui.controls.FontAwesome5IconView?>
+<?import javafx.scene.shape.Circle?>
+<?import javafx.scene.Group?>
+<HBox xmlns:fx="http://javafx.com/fxml"
 	  xmlns="http://javafx.com/javafx"
 	  fx:controller="org.cryptomator.ui.recoverykey.RecoveryKeyResetPasswordController"
 	  minWidth="400"
@@ -17,17 +22,28 @@
 		<Insets topRightBottomLeft="12"/>
 	</padding>
 	<children>
-		<fx:include fx:id="newPassword" source="new_password.fxml"/>
+		<Group>
+			<StackPane>
+				<padding>
+					<Insets topRightBottomLeft="6"/>
+				</padding>
+				<Circle styleClass="glyph-icon-primary" radius="24"/>
+				<FontAwesome5IconView styleClass="glyph-icon-white" glyph="KEY" glyphSize="24"/>
+			</StackPane>
+		</Group>
+		<VBox spacing="12" HBox.hgrow="ALWAYS" alignment="TOP_CENTER">
+			<fx:include fx:id="newPassword" source="new_password.fxml"/>
 
-		<Region VBox.vgrow="ALWAYS"/>
+			<Region VBox.vgrow="ALWAYS"/>
 
-		<VBox alignment="BOTTOM_CENTER" VBox.vgrow="ALWAYS">
-			<ButtonBar buttonMinWidth="120" buttonOrder="+CI">
-				<buttons>
-					<Button text="%generic.button.back" ButtonBar.buttonData="CANCEL_CLOSE" cancelButton="true" onAction="#close"/>
-					<Button fx:id="nextButton" ButtonBar.buttonData="FINISH" defaultButton="true" disable="${!controller.passwordSufficientAndMatching}" onAction="#next"/>
-				</buttons>
-			</ButtonBar>
+			<VBox alignment="BOTTOM_CENTER" VBox.vgrow="ALWAYS">
+				<ButtonBar buttonMinWidth="120" buttonOrder="+CI">
+					<buttons>
+						<Button text="%generic.button.back" ButtonBar.buttonData="CANCEL_CLOSE" cancelButton="true" onAction="#close"/>
+						<Button fx:id="nextButton" ButtonBar.buttonData="FINISH" defaultButton="true" disable="${!controller.passwordSufficientAndMatching}" onAction="#next"/>
+					</buttons>
+				</ButtonBar>
+			</VBox>
 		</VBox>
 	</children>
-</VBox>
+</HBox>

+ 8 - 15
src/main/resources/fxml/recoverykey_validate.fxml

@@ -2,48 +2,41 @@
 
 <?import org.cryptomator.ui.controls.FontAwesome5IconView?>
 <?import org.cryptomator.ui.controls.FormattedLabel?>
-<?import javafx.geometry.Insets?>
 <?import javafx.scene.control.Label?>
 <?import javafx.scene.control.TextArea?>
-<?import javafx.scene.layout.StackPane?>
 <?import javafx.scene.layout.VBox?>
 <VBox xmlns:fx="http://javafx.com/fxml"
 	  xmlns="http://javafx.com/javafx"
 	  fx:controller="org.cryptomator.ui.recoverykey.RecoveryKeyValidateController"
-	  minWidth="400"
 	  maxWidth="400"
 	  minHeight="145"
-	  spacing="12"
-	  alignment="TOP_CENTER">
-	<padding>
-		<Insets topRightBottomLeft="12"/>
-	</padding>
+	  spacing="12">
 	<children>
 		<FormattedLabel format="%recoveryKey.recover.prompt" arg1="${controller.vault.displayName}" wrapText="true"/>
 
 		<TextArea wrapText="true" prefRowCount="4" fx:id="textarea" textFormatter="${controller.recoveryKeyTextFormatter}" onKeyPressed="#onKeyPressed"/>
-
-		<StackPane>
-			<Label text="Just some Filler" visible="false" graphicTextGap="6">
+		<VBox>
+			<Label text="Just some Filler" visible="false" managed="${textarea.text.empty}" graphicTextGap="6">
 				<graphic>
 					<FontAwesome5IconView glyph="ANCHOR"/>
 				</graphic>
 			</Label>
-			<Label text="%recoveryKey.recover.correctKey" graphicTextGap="6" contentDisplay="LEFT" visible="${(!textarea.text.empty) &amp;&amp; controller.recoveryKeyCorrect}">
+			<Label text="%recoveryKey.recover.correctKey" graphicTextGap="6" visible="${(!textarea.text.empty) &amp;&amp; controller.recoveryKeyCorrect}" managed="${(!textarea.text.empty) &amp;&amp; controller.recoveryKeyCorrect}">
 				<graphic>
 					<FontAwesome5IconView glyph="CHECK"/>
 				</graphic>
 			</Label>
-			<Label text="%recoveryKey.recover.wrongKey" graphicTextGap="6" contentDisplay="LEFT" visible="${(!textarea.text.empty) &amp;&amp; controller.recoveryKeyWrong}">
+			<Label text="%recoveryKey.recover.wrongKey" graphicTextGap="6"  visible="${(!textarea.text.empty) &amp;&amp; controller.recoveryKeyWrong}" managed="${(!textarea.text.empty) &amp;&amp; controller.recoveryKeyWrong}">
 				<graphic>
 					<FontAwesome5IconView glyph="TIMES" styleClass="glyph-icon-red"/>
 				</graphic>
 			</Label>
-			<Label text="%recoveryKey.recover.invalidKey" graphicTextGap="6" contentDisplay="LEFT" visible="${(!textarea.text.empty) &amp;&amp; controller.recoveryKeyInvalid}">
+			<Label text="%recoveryKey.recover.invalidKey" graphicTextGap="6"  visible="${(!textarea.text.empty) &amp;&amp; controller.recoveryKeyInvalid}" managed="${(!textarea.text.empty) &amp;&amp; controller.recoveryKeyInvalid}">
 				<graphic>
 					<FontAwesome5IconView glyph="TIMES" styleClass="glyph-icon-red"/>
 				</graphic>
 			</Label>
-		</StackPane>
+		</VBox>
+
 	</children>
 </VBox>

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

@@ -112,9 +112,9 @@ removeVault.message=Remove vault?
 removeVault.description=This will only make Cryptomator forget about this vault. You can add it again. No encrypted files will be deleted from your hard drive.
 
 # Contact Hub Admin
-contactHubAdmin.title=Contact Admin
-contactHubAdmin.message=Contact Admin
-contactHubAdmin.description=You should contact your vault admin.
+contactHubAdmin.title=Hub Vault
+contactHubAdmin.message=This vault was created with Cryptomator Hub
+contactHubAdmin.description=Please reach out to the vault owner to restore the missing file. They can download the vault template from Cryptomator Hub.
 
 # Change Password
 changepassword.title=Change Password
@@ -545,24 +545,21 @@ recoveryKey.alreadyExists.message=This vault has already been added
 recoveryKey.alreadyExists.description=Your vault "%s" is already present in your vault list and was therefore not added again.
 
 recoveryKey.noDDirDetected.title=Invalid Selection
+recoveryKey.noDDirDetected.message=Your selection is not a vault
 recoveryKey.noDDirDetected.description=The selected folder must contain a subfolder named "d".
-recoveryKey.noDDirDetected.message=Please choose a different folder that includes a subfolder named "d".
 
 recoveryKey.recoverVaultConfig.title=Recover Vault Config
 recoveryKey.recoverMasterkey.title=Recover Masterkey
 
+recoveryKey.recover.expertSettings.shorteningThreshold.title=This value must match the one used before recovery to ensure compatibility with previously encrypted data.
 
-recoveryKey.recover.onBoarding.recoverMasterkey.title=Restore your vault.cryptomator file
+recoveryKey.recover.onBoarding.readThis=Make sure to check the following:
+recoveryKey.recover.onBoarding.message=If your vault is a Hub vault, the vault owner can restore the file for you. Otherwise:
+recoveryKey.recover.onBoarding.intro1=Ensure all files are completely synced.
+recoveryKey.recover.onBoarding.recoverVaultConfig.intro2.recoveryKey=You will need the recovery key, a new vault password and possibly some expert settings.
+recoveryKey.recover.onBoarding.recoverVaultConfig.intro2.password=You will need the vault password and possibly some expert settings.
 recoveryKey.recover.onBoarding.recoverMasterkey.intro2=You will need the vault recovery key.
-recoveryKey.recover.onBoarding.recoverVaultConfig.intro2=You will need the vault password or recovery key, a new password and possible some expert settings.
 
-recoveryKey.recover.onBoarding.readThis=Read this:
-recoveryKey.recover.onBoarding.message=If your vault is a hub managed vault, the Hub Admin can restore the file for you. Otherwise:
-recoveryKey.recover.onBoarding.description=Otherwise you will need the Recovery Key of the vault, possible some expert settings, and a new vault password.
-recoveryKey.recover.onBoarding.confirm=Use RecoveryKey
-recoveryKey.recover.onBoarding.intro1=Ensure all files are completely synced.
-recoveryKey.recover.onBoarding.intro2=You will need the Recovery Key of the vault.
-recoveryKey.recover.onBoarding.intro3=A new vault password and possible some expert settings.
 recoveryKey.recover.onBoarding.chooseMethod=Choose recovery method:
 recoveryKey.recover.onBoarding.useRecoveryKey=Use Recovery Key
 recoveryKey.recover.onBoarding.usePassword=Use Password