Merge pull request #2319 from cryptomator/feature/hub-better-dialogs

Improve Hub dialogs
This commit is contained in:
Armin Schrenk
2022-07-07 20:54:11 +02:00
committed by GitHub
15 changed files with 378 additions and 94 deletions

View File

@@ -16,6 +16,8 @@ public enum FxmlFile {
HUB_AUTH_FLOW("/fxml/hub_auth_flow.fxml"), //
HUB_RECEIVE_KEY("/fxml/hub_receive_key.fxml"), //
HUB_REGISTER_DEVICE("/fxml/hub_register_device.fxml"), //
HUB_REGISTER_SUCCESS("/fxml/hub_register_success.fxml"), //
HUB_REGISTER_FAILED("/fxml/hub_register_failed.fxml"),
HUB_UNAUTHORIZED_DEVICE("/fxml/hub_unauthorized_device.fxml"), //
LOCK_FORCED("/fxml/lock_forced.fxml"), //
LOCK_FAILED("/fxml/lock_failed.fxml"), //

View File

@@ -38,7 +38,6 @@ public class AuthFlowController implements FxController {
private final CompletableFuture<JWEObject> result;
private final Lazy<Scene> receiveKeyScene;
private final ObjectProperty<URI> authUri;
private final StringBinding authHost;
private AuthFlowTask task;
@Inject
@@ -52,7 +51,6 @@ public class AuthFlowController implements FxController {
this.result = result;
this.receiveKeyScene = receiveKeyScene;
this.authUri = new SimpleObjectProperty<>();
this.authHost = Bindings.createStringBinding(this::getAuthHost, authUri);
this.window.addEventHandler(WindowEvent.WINDOW_HIDING, this::windowClosed);
}
@@ -100,19 +98,4 @@ public class AuthFlowController implements FxController {
result.completeExceptionally(exception);
}
/* Getter/Setter */
public StringBinding authHostProperty() {
return authHost;
}
public String getAuthHost() {
var uri = authUri.get();
if (uri == null) {
return "";
} else {
return uri.getAuthority().toString();
}
}
}

View File

@@ -43,6 +43,14 @@ public abstract class HubKeyLoadingModule {
}
}
@Provides
@KeyLoadingScoped
@Named("windowTitle")
static String provideWindowTitle(@KeyLoading Vault vault, ResourceBundle resourceBundle) {
return String.format(resourceBundle.getString("unlock.title"), vault.getDisplayName());
}
@Provides
@KeyLoadingScoped
@Named("deviceId")
@@ -98,6 +106,20 @@ public abstract class HubKeyLoadingModule {
return fxmlLoaders.createScene(FxmlFile.HUB_REGISTER_DEVICE);
}
@Provides
@FxmlScene(FxmlFile.HUB_REGISTER_SUCCESS)
@KeyLoadingScoped
static Scene provideHubRegisterSuccessScene(@KeyLoading FxmlLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene(FxmlFile.HUB_REGISTER_SUCCESS);
}
@Provides
@FxmlScene(FxmlFile.HUB_REGISTER_FAILED)
@KeyLoadingScoped
static Scene provideHubRegisterFailedScene(@KeyLoading FxmlLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene(FxmlFile.HUB_REGISTER_FAILED);
}
@Provides
@FxmlScene(FxmlFile.HUB_UNAUTHORIZED_DEVICE)
@KeyLoadingScoped
@@ -127,6 +149,16 @@ public abstract class HubKeyLoadingModule {
@FxControllerKey(RegisterDeviceController.class)
abstract FxController bindRegisterDeviceController(RegisterDeviceController controller);
@Binds
@IntoMap
@FxControllerKey(RegisterSuccessController.class)
abstract FxController bindRegisterSuccessController(RegisterSuccessController controller);
@Binds
@IntoMap
@FxControllerKey(RegisterFailedController.class)
abstract FxController bindRegisterFailedController(RegisterFailedController controller);
@Binds
@IntoMap
@FxControllerKey(UnauthorizedDeviceController.class)

View File

@@ -13,6 +13,7 @@ import org.cryptomator.ui.keyloading.KeyLoadingStrategy;
import org.cryptomator.ui.unlock.UnlockCancelledException;
import javax.inject.Inject;
import javax.inject.Named;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.stage.Stage;
@@ -35,8 +36,9 @@ public class HubKeyLoadingStrategy implements KeyLoadingStrategy {
private final DeviceKey deviceKey;
@Inject
public HubKeyLoadingStrategy(@KeyLoading Stage window, @FxmlScene(FxmlFile.HUB_AUTH_FLOW) Lazy<Scene> authFlowScene, CompletableFuture<JWEObject> result, DeviceKey deviceKey) {
public HubKeyLoadingStrategy(@KeyLoading Stage window, @FxmlScene(FxmlFile.HUB_AUTH_FLOW) Lazy<Scene> authFlowScene, CompletableFuture<JWEObject> result, DeviceKey deviceKey, @Named("windowTitle") String windowTitle) {
this.window = window;
window.setTitle(windowTitle);
this.authFlowScene = authFlowScene;
this.result = result;
this.deviceKey = deviceKey;

View File

@@ -35,7 +35,6 @@ import java.util.concurrent.atomic.AtomicReference;
@KeyLoadingScoped
public class ReceiveKeyController implements FxController {
private static final Logger LOG = LoggerFactory.getLogger(ReceiveKeyController.class);
private static final String SCHEME_PREFIX = "hub+";
private final Stage window;

View File

@@ -6,9 +6,12 @@ import com.google.common.io.BaseEncoding;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.nimbusds.jose.JWEObject;
import dagger.Lazy;
import org.cryptomator.common.settings.DeviceKey;
import org.cryptomator.cryptolib.common.P384KeyPair;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.common.FxmlFile;
import org.cryptomator.ui.common.FxmlScene;
import org.cryptomator.ui.keyloading.KeyLoading;
import org.cryptomator.ui.keyloading.KeyLoadingScoped;
import org.slf4j.Logger;
@@ -18,9 +21,12 @@ import javax.inject.Inject;
import javax.inject.Named;
import javafx.application.Platform;
import javafx.fxml.FXML;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
import java.io.IOException;
import java.net.InetAddress;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
@@ -40,6 +46,8 @@ public class RegisterDeviceController implements FxController {
private final Stage window;
private final HubConfig hubConfig;
private final String bearerToken;
private final Lazy<Scene> registerSuccessScene;
private final Lazy<Scene> registerFailedScene;
private final String deviceId;
private final P384KeyPair keyPair;
private final CompletableFuture<JWEObject> result;
@@ -49,18 +57,33 @@ public class RegisterDeviceController implements FxController {
public TextField deviceNameField;
@Inject
public RegisterDeviceController(@KeyLoading Stage window, ExecutorService executor, HubConfig hubConfig, @Named("deviceId") String deviceId, DeviceKey deviceKey, CompletableFuture<JWEObject> result, @Named("bearerToken") AtomicReference<String> bearerToken) {
public RegisterDeviceController(@KeyLoading Stage window, ExecutorService executor, HubConfig hubConfig, @Named("deviceId") String deviceId, DeviceKey deviceKey, CompletableFuture<JWEObject> result, @Named("bearerToken") AtomicReference<String> bearerToken, @FxmlScene(FxmlFile.HUB_REGISTER_SUCCESS) Lazy<Scene> registerSuccessScene, @FxmlScene(FxmlFile.HUB_REGISTER_FAILED) Lazy<Scene> registerFailedScene) {
this.window = window;
this.hubConfig = hubConfig;
this.deviceId = deviceId;
this.keyPair = Objects.requireNonNull(deviceKey.get());
this.result = result;
this.bearerToken = Objects.requireNonNull(bearerToken.get());
this.registerSuccessScene = registerSuccessScene;
this.registerFailedScene = registerFailedScene;
this.jwt = JWT.decode(this.bearerToken);
this.window.addEventHandler(WindowEvent.WINDOW_HIDING, this::windowClosed);
this.httpClient = HttpClient.newBuilder().executor(executor).build();
}
public void initialize() {
deviceNameField.setText(determineHostname());
}
private String determineHostname() {
try {
var hostName = InetAddress.getLocalHost().getHostName();
return Objects.requireNonNullElse(hostName, "");
} catch (IOException e) {
return "";
}
}
@FXML
public void register() {
var keyUri = URI.create(hubConfig.devicesResourceUrl + deviceId);
@@ -75,18 +98,25 @@ public class RegisterDeviceController implements FxController {
.header("Content-Type", "application/json").PUT(HttpRequest.BodyPublishers.ofString(json, StandardCharsets.UTF_8)) //
.build();
httpClient.sendAsync(request, HttpResponse.BodyHandlers.discarding()) //
.thenAcceptAsync(this::registrationSucceeded, Platform::runLater) //
.exceptionally(this::registrationFailed);
.handleAsync((response, throwable) -> {
if (response != null) {
this.registrationSucceeded(response);
} else {
this.registrationFailed(throwable);
}
return null;
}, Platform::runLater);
}
private void registrationSucceeded(HttpResponse<Void> voidHttpResponse) {
LOG.info("Registered!");
window.close(); // TODO: show visual feedback "please wait for device authorization"
LOG.debug("Device registration for hub instance {} successful.", hubConfig.authSuccessUrl);
window.setScene(registerSuccessScene.get());
}
private Void registrationFailed(Throwable cause) {
private void registrationFailed(Throwable cause) {
LOG.warn("Device registration failed.", cause);
window.setScene(registerFailedScene.get());
result.completeExceptionally(cause);
return null;
}
@FXML

View File

@@ -0,0 +1,29 @@
package org.cryptomator.ui.keyloading.hub;
import com.nimbusds.jose.JWEObject;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.keyloading.KeyLoading;
import javax.inject.Inject;
import javafx.fxml.FXML;
import javafx.stage.Stage;
import java.util.concurrent.CompletableFuture;
public class RegisterFailedController implements FxController {
private final Stage window;
private final CompletableFuture<JWEObject> result;
@Inject
public RegisterFailedController(@KeyLoading Stage window, CompletableFuture<JWEObject> result) {
this.window = window;
this.result = result;
}
@FXML
public void close() {
window.close();
}
}

View File

@@ -0,0 +1,24 @@
package org.cryptomator.ui.keyloading.hub;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.keyloading.KeyLoading;
import javax.inject.Inject;
import javafx.fxml.FXML;
import javafx.stage.Stage;
public class RegisterSuccessController implements FxController {
private final Stage window;
@Inject
public RegisterSuccessController(@KeyLoading Stage window) {
this.window = window;
}
@FXML
public void close() {
window.close();
}
}

View File

@@ -1,37 +1,58 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import org.cryptomator.ui.controls.FontAwesome5Spinner?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ButtonBar?>
<?import javafx.scene.control.Hyperlink?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.Group?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.Region?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Text?>
<?import javafx.scene.shape.Circle?>
<?import javafx.scene.text.TextFlow?>
<VBox xmlns:fx="http://javafx.com/fxml"
<?import org.cryptomator.ui.controls.FontAwesome5IconView?>
<HBox xmlns:fx="http://javafx.com/fxml"
xmlns="http://javafx.com/javafx"
fx:controller="org.cryptomator.ui.keyloading.hub.AuthFlowController"
minWidth="400"
maxWidth="400"
minHeight="145"
spacing="12">
spacing="12"
alignment="TOP_LEFT">
<padding>
<Insets topRightBottomLeft="12"/>
</padding>
<children>
<HBox spacing="12" VBox.vgrow="ALWAYS">
<ImageView VBox.vgrow="ALWAYS" fitWidth="64" preserveRatio="true" cache="true">
<Image url="@../img/bot/bot.png"/>
</ImageView>
<TextFlow visible="${!controller.authHost.empty}" managed="${!controller.authHost.empty}">
<Text text="TODO: please login via " />
<Hyperlink styleClass="hyperlink-underline" text="${controller.authHost}" onAction="#browse"/>
</TextFlow>
</HBox>
<Group>
<StackPane>
<padding>
<Insets topRightBottomLeft="6"/>
</padding>
<Circle styleClass="glyph-icon-primary" radius="24"/>
<FontAwesome5Spinner styleClass="glyph-icon-white" glyphSize="24"/>
</StackPane>
</Group>
<VBox alignment="BOTTOM_CENTER" VBox.vgrow="ALWAYS">
<VBox HBox.hgrow="ALWAYS">
<Label styleClass="label-large" text="%hub.auth.message" wrapText="true" textAlignment="LEFT">
<padding>
<Insets bottom="6" top="6"/>
</padding>
</Label>
<Label text="%hub.auth.description" wrapText="true"/>
<Hyperlink styleClass="hyperlink-underline" text="%hub.auth.loginLink" onAction="#browse">
<graphic>
<FontAwesome5IconView glyph="LINK" glyphSize="12"/>
</graphic>
<padding>
<Insets top="12"/>
</padding>
</Hyperlink>
<Region VBox.vgrow="ALWAYS" minHeight="18"/>
<ButtonBar buttonMinWidth="120" buttonOrder="+C">
<buttons>
<Button text="%generic.button.cancel" ButtonBar.buttonData="CANCEL_CLOSE" cancelButton="true" onAction="#cancel"/>
@@ -39,4 +60,4 @@
</ButtonBar>
</VBox>
</children>
</VBox>
</HBox>

View File

@@ -4,30 +4,44 @@
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ButtonBar?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.Group?>
<?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?>
<HBox xmlns:fx="http://javafx.com/fxml"
xmlns="http://javafx.com/javafx"
fx:controller="org.cryptomator.ui.keyloading.hub.ReceiveKeyController"
minWidth="400"
maxWidth="400"
minHeight="145"
spacing="12">
spacing="12"
alignment="TOP_LEFT">
<padding>
<Insets topRightBottomLeft="12"/>
</padding>
<children>
<HBox spacing="12" VBox.vgrow="ALWAYS">
<ImageView VBox.vgrow="ALWAYS" fitWidth="64" preserveRatio="true" cache="true">
<Image url="@../img/bot/bot.png"/>
</ImageView>
<Group>
<StackPane>
<padding>
<Insets topRightBottomLeft="6"/>
</padding>
<Circle styleClass="glyph-icon-primary" radius="24"/>
<FontAwesome5Spinner styleClass="glyph-icon-white" glyphSize="24"/>
</StackPane>
</Group>
<FontAwesome5Spinner glyphSize="12"/>
</HBox>
<VBox HBox.hgrow="ALWAYS">
<Label styleClass="label-large" text="%hub.receive.message" wrapText="true" textAlignment="LEFT">
<padding>
<Insets bottom="6" top="6"/>
</padding>
</Label>
<Label text="%hub.receive.description" wrapText="true"/>
<VBox alignment="BOTTOM_CENTER" VBox.vgrow="ALWAYS">
<Region VBox.vgrow="ALWAYS" minHeight="18"/>
<ButtonBar buttonMinWidth="120" buttonOrder="+C">
<buttons>
<Button text="%generic.button.cancel" ButtonBar.buttonData="CANCEL_CLOSE" cancelButton="true" onAction="#cancel"/>
@@ -35,4 +49,4 @@
</ButtonBar>
</VBox>
</children>
</VBox>
</HBox>

View File

@@ -1,52 +1,61 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import org.cryptomator.ui.controls.FormattedLabel?>
<?import org.cryptomator.ui.controls.FontAwesome5IconView?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ButtonBar?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.Group?>
<?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?>
<HBox xmlns:fx="http://javafx.com/fxml"
xmlns="http://javafx.com/javafx"
fx:controller="org.cryptomator.ui.keyloading.hub.RegisterDeviceController"
minWidth="400"
maxWidth="400"
minHeight="145"
spacing="12">
spacing="12"
alignment="TOP_LEFT">
<padding>
<Insets topRightBottomLeft="12"/>
</padding>
<children>
<HBox spacing="12" VBox.vgrow="ALWAYS">
<HBox alignment="CENTER">
<ImageView VBox.vgrow="ALWAYS" fitWidth="64" preserveRatio="true" cache="true">
<Image url="@../img/bot/bot.png"/>
</ImageView>
<Group>
<StackPane>
<padding>
<Insets topRightBottomLeft="6"/>
</padding>
<Circle styleClass="glyph-icon-primary" radius="24"/>
<FontAwesome5IconView styleClass="glyph-icon-white" glyph="INFO" glyphSize="24"/>
</StackPane>
</Group>
<VBox HBox.hgrow="ALWAYS">
<Label styleClass="label-large" text="%hub.register.message" wrapText="true" textAlignment="LEFT">
<padding>
<Insets bottom="6" top="6"/>
</padding>
</Label>
<Label text="%hub.register.description" wrapText="true"/>
<HBox spacing="6" alignment="CENTER_LEFT">
<padding>
<Insets top="12"/>
</padding>
<Label text="%hub.register.nameLabel" labelFor="$deviceNameField"/>
<TextField fx:id="deviceNameField" HBox.hgrow="ALWAYS"/>
</HBox>
<VBox spacing="6">
<Label text="TODO This device is not yet known to Cryptomator Hub. Please register this device first." wrapText="true"/>
<HBox spacing="6" alignment="CENTER_LEFT">
<FormattedLabel format="TODO User %s" arg1="${controller.userName}"/>
</HBox>
<HBox spacing="6" alignment="CENTER_LEFT">
<Label text="TODO Device Name" labelFor="$deviceNameField"/>
<TextField fx:id="deviceNameField"/>
</HBox>
</VBox>
</HBox>
<VBox alignment="BOTTOM_CENTER" VBox.vgrow="ALWAYS">
<Region VBox.vgrow="ALWAYS" minHeight="18"/>
<ButtonBar buttonMinWidth="120" buttonOrder="+CU">
<buttons>
<Button text="%generic.button.close" ButtonBar.buttonData="CANCEL_CLOSE" cancelButton="true" onAction="#close"/>
<Button text="TODO Register Device" ButtonBar.buttonData="OTHER" defaultButton="true" onAction="#register"/>
<Button text="%hub.register.registerBtn" ButtonBar.buttonData="OTHER" defaultButton="true" onAction="#register"/>
</buttons>
</ButtonBar>
</VBox>
</children>
</VBox>
</HBox>

View File

@@ -0,0 +1,51 @@
<?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.control.ButtonBar?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.Group?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.Region?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.shape.Circle?>
<HBox xmlns:fx="http://javafx.com/fxml"
xmlns="http://javafx.com/javafx"
fx:controller="org.cryptomator.ui.keyloading.hub.RegisterFailedController"
minWidth="400"
maxWidth="400"
minHeight="145"
spacing="12"
alignment="TOP_LEFT">
<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="EXCLAMATION" glyphSize="24"/>
</StackPane>
</Group>
<VBox HBox.hgrow="ALWAYS">
<Label styleClass="label-large" text="%hub.registerFailed.message" wrapText="true" textAlignment="LEFT">
<padding>
<Insets bottom="6" top="6"/>
</padding>
</Label>
<Label text="%hub.registerFailed.description" wrapText="true"/>
<Region VBox.vgrow="ALWAYS" minHeight="18"/>
<ButtonBar buttonMinWidth="120" buttonOrder="+C">
<buttons>
<Button text="%generic.button.close" ButtonBar.buttonData="CANCEL_CLOSE" defaultButton="true" onAction="#close"/>
</buttons>
</ButtonBar>
</VBox>
</children>
</HBox>

View File

@@ -0,0 +1,52 @@
<?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.control.ButtonBar?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.Group?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.Region?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.shape.Circle?>
<HBox xmlns:fx="http://javafx.com/fxml"
xmlns="http://javafx.com/javafx"
fx:controller="org.cryptomator.ui.keyloading.hub.RegisterSuccessController"
minWidth="400"
maxWidth="400"
minHeight="145"
spacing="12"
alignment="TOP_LEFT">
<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="CHECK" glyphSize="24"/>
</StackPane>
</Group>
<VBox HBox.hgrow="ALWAYS">
<Label styleClass="label-large" text="%hub.registerSuccess.message" wrapText="true" textAlignment="LEFT">
<padding>
<Insets bottom="6" top="6"/>
</padding>
</Label>
<Label text="%hub.registerSuccess.description" wrapText="true"/>
<Region VBox.vgrow="ALWAYS" minHeight="18"/>
<ButtonBar buttonMinWidth="120" buttonOrder="+C">
<buttons>
<Button text="%generic.button.close" ButtonBar.buttonData="CANCEL_CLOSE" defaultButton="true" onAction="#close"/>
<!-- TODO: add request access button -->
</buttons>
</ButtonBar>
</VBox>
</children>
</HBox>

View File

@@ -1,40 +1,53 @@
<?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.control.ButtonBar?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.Group?>
<?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?>
<HBox xmlns:fx="http://javafx.com/fxml"
xmlns="http://javafx.com/javafx"
fx:controller="org.cryptomator.ui.keyloading.hub.UnauthorizedDeviceController"
minWidth="400"
maxWidth="400"
minHeight="145"
spacing="12">
spacing="12"
alignment="TOP_LEFT">
<padding>
<Insets topRightBottomLeft="12"/>
</padding>
<children>
<HBox spacing="12" VBox.vgrow="ALWAYS">
<ImageView VBox.vgrow="ALWAYS" fitWidth="64" preserveRatio="true" cache="true">
<Image url="@../img/bot/bot.png"/>
</ImageView>
<Group>
<StackPane>
<padding>
<Insets topRightBottomLeft="6"/>
</padding>
<Circle styleClass="glyph-icon-primary" radius="24"/>
<FontAwesome5IconView styleClass="glyph-icon-white" glyph="BAN" glyphSize="24"/>
</StackPane>
</Group>
<VBox HBox.hgrow="ALWAYS">
<Label styleClass="label-large" text="%hub.unauthorized.message" wrapText="true" textAlignment="LEFT">
<padding>
<Insets bottom="6" top="6"/>
</padding>
</Label>
<Label text="%hub.unauthorized.description" wrapText="true"/>
<VBox spacing="12">
<Label text="TODO: Your device has not yet been authorized to access this vault. Ask the vault owner to authorize it." wrapText="true"/>
</VBox>
</HBox>
<VBox alignment="BOTTOM_CENTER" VBox.vgrow="ALWAYS">
<Region VBox.vgrow="ALWAYS" minHeight="18"/>
<ButtonBar buttonMinWidth="120" buttonOrder="+C">
<buttons>
<Button text="%generic.button.close" ButtonBar.buttonData="CANCEL_CLOSE" defaultButton="true" onAction="#close"/>
<!-- TODO: add request access button -->
<!--Button text="%generic.button.close" ButtonBar.buttonData="CANCEL_CLOSE" defaultButton="true" onAction="#close"/-->
</buttons>
</ButtonBar>
</VBox>
</children>
</VBox>
</HBox>

View File

@@ -124,6 +124,29 @@ unlock.error.message=Unable to unlock vault
unlock.error.invalidMountPoint.notExisting=Mount point "%s" is not a directory, not empty or does not exist.
unlock.error.invalidMountPoint.existing=Mount point "%s" already exists or parent folder is missing.
unlock.error.invalidMountPoint.driveLetterOccupied=Drive Letter "%s" is already in use.
## Hub
### Waiting
hub.auth.message=Waiting for authentication…
hub.auth.description=You should automatically be redirected to the login page.
hub.auth.loginLink=Not redirected? Click here to open it.
### Receive Key
hub.receive.message=Processing response…
hub.receive.description=Cryptomator is receiving and processing the response from Hub. Please wait.
### Register Device
hub.register.message=Device name required
hub.register.description=This seems to be the first Hub access from this device. In order to identify it for access authorization, you need to name this device.
hub.register.nameLabel=Device Name
hub.register.registerBtn=Confirm
### Registration Success
hub.registerSuccess.message=Device named
hub.registerSuccess.description=To access the vault, your device needs to be authorized by the vault owner.
### Registration Failed
hub.registerFailed.message=Device naming failed
hub.registerFailed.description=An error was thrown in the naming process. For more details, look into the application log.
### Unauthorized
hub.unauthorized.message=Access denied
hub.unauthorized.description=Your device has not yet been authorized to access this vault. Ask the vault owner to authorize it.
# Lock
## Force