mirror of
https://github.com/cryptomator/cryptomator.git
synced 2026-04-18 16:46:53 -04:00
Merge pull request #3289 from cryptomator/feature/share-vault
Feature: Introduce 'Share Vault' Functionality
This commit is contained in:
@@ -45,6 +45,7 @@ public enum FxmlFile {
|
||||
RECOVERYKEY_RESET_PASSWORD_SUCCESS("/fxml/recoverykey_reset_password_success.fxml"), //
|
||||
RECOVERYKEY_SUCCESS("/fxml/recoverykey_success.fxml"), //
|
||||
REMOVE_VAULT("/fxml/remove_vault.fxml"), //
|
||||
SHARE_VAULT("/fxml/share_vault.fxml"), //
|
||||
UPDATE_REMINDER("/fxml/update_reminder.fxml"), //
|
||||
UNLOCK_ENTER_PASSWORD("/fxml/unlock_enter_password.fxml"),
|
||||
UNLOCK_REQUIRES_RESTART("/fxml/unlock_requires_restart.fxml"), //
|
||||
|
||||
@@ -47,6 +47,7 @@ public enum FontAwesome5Icon {
|
||||
QUESTION_CIRCLE("\uf059"), //
|
||||
REDO("\uF01E"), //
|
||||
SEARCH("\uF002"), //
|
||||
SHARE("\uF064"), //
|
||||
SPINNER("\uF110"), //
|
||||
STETHOSCOPE("\uF0f1"), //
|
||||
SYNC("\uF021"), //
|
||||
|
||||
@@ -13,6 +13,7 @@ import org.cryptomator.ui.lock.LockComponent;
|
||||
import org.cryptomator.ui.mainwindow.MainWindowComponent;
|
||||
import org.cryptomator.ui.preferences.PreferencesComponent;
|
||||
import org.cryptomator.ui.quit.QuitComponent;
|
||||
import org.cryptomator.ui.sharevault.ShareVaultComponent;
|
||||
import org.cryptomator.ui.traymenu.TrayMenuComponent;
|
||||
import org.cryptomator.ui.unlock.UnlockComponent;
|
||||
import org.cryptomator.ui.updatereminder.UpdateReminderComponent;
|
||||
@@ -22,7 +23,17 @@ import javafx.scene.image.Image;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
@Module(includes = {UpdateCheckerModule.class}, subcomponents = {TrayMenuComponent.class, MainWindowComponent.class, PreferencesComponent.class, VaultOptionsComponent.class, UnlockComponent.class, LockComponent.class, QuitComponent.class, ErrorComponent.class, HealthCheckComponent.class, UpdateReminderComponent.class})
|
||||
@Module(includes = {UpdateCheckerModule.class}, subcomponents = {TrayMenuComponent.class, //
|
||||
MainWindowComponent.class, //
|
||||
PreferencesComponent.class, //
|
||||
VaultOptionsComponent.class, //
|
||||
UnlockComponent.class, //
|
||||
LockComponent.class, //
|
||||
QuitComponent.class, //
|
||||
ErrorComponent.class, //
|
||||
HealthCheckComponent.class, //
|
||||
UpdateReminderComponent.class, //
|
||||
ShareVaultComponent.class})
|
||||
abstract class FxApplicationModule {
|
||||
|
||||
private static Image createImageFromResource(String resourceName) throws IOException {
|
||||
|
||||
@@ -11,6 +11,7 @@ import org.cryptomator.ui.mainwindow.MainWindowComponent;
|
||||
import org.cryptomator.ui.preferences.PreferencesComponent;
|
||||
import org.cryptomator.ui.preferences.SelectedPreferencesTab;
|
||||
import org.cryptomator.ui.quit.QuitComponent;
|
||||
import org.cryptomator.ui.sharevault.ShareVaultComponent;
|
||||
import org.cryptomator.ui.unlock.UnlockComponent;
|
||||
import org.cryptomator.ui.unlock.UnlockWorkflow;
|
||||
import org.cryptomator.ui.updatereminder.UpdateReminderComponent;
|
||||
@@ -51,6 +52,7 @@ public class FxApplicationWindows {
|
||||
private final ErrorComponent.Factory errorWindowFactory;
|
||||
private final ExecutorService executor;
|
||||
private final VaultOptionsComponent.Factory vaultOptionsWindow;
|
||||
private final ShareVaultComponent.Factory shareVaultWindow;
|
||||
private final FilteredList<Window> visibleWindows;
|
||||
|
||||
@Inject
|
||||
@@ -64,6 +66,7 @@ public class FxApplicationWindows {
|
||||
LockComponent.Factory lockWorkflowFactory, //
|
||||
ErrorComponent.Factory errorWindowFactory, //
|
||||
VaultOptionsComponent.Factory vaultOptionsWindow, //
|
||||
ShareVaultComponent.Factory shareVaultWindow, //
|
||||
ExecutorService executor) {
|
||||
this.primaryStage = primaryStage;
|
||||
this.trayIntegration = trayIntegration;
|
||||
@@ -76,6 +79,7 @@ public class FxApplicationWindows {
|
||||
this.errorWindowFactory = errorWindowFactory;
|
||||
this.executor = executor;
|
||||
this.vaultOptionsWindow = vaultOptionsWindow;
|
||||
this.shareVaultWindow = shareVaultWindow;
|
||||
this.visibleWindows = Window.getWindows().filtered(Window::isShowing);
|
||||
}
|
||||
|
||||
@@ -122,6 +126,10 @@ public class FxApplicationWindows {
|
||||
return CompletableFuture.supplyAsync(() -> preferencesWindow.get().showPreferencesWindow(selectedTab), Platform::runLater).whenComplete(this::reportErrors);
|
||||
}
|
||||
|
||||
public void showShareVaultWindow(Vault vault) {
|
||||
CompletableFuture.runAsync(() -> shareVaultWindow.create(vault).showShareVaultWindow(), Platform::runLater);
|
||||
}
|
||||
|
||||
public CompletionStage<Stage> showVaultOptionsWindow(Vault vault, SelectedVaultOptionsTab tab) {
|
||||
return showMainWindow().thenApplyAsync((window) -> vaultOptionsWindow.create(vault).showVaultOptionsWindow(tab), Platform::runLater).whenComplete(this::reportErrors);
|
||||
}
|
||||
|
||||
@@ -44,6 +44,11 @@ public class VaultDetailLockedController implements FxController {
|
||||
appWindows.startUnlockWorkflow(vault.get(), mainWindow);
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void share() {
|
||||
appWindows.showShareVaultWindow(vault.get());
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void showVaultOptions() {
|
||||
vaultOptionsWindow.create(vault.get()).showVaultOptionsWindow(SelectedVaultOptionsTab.ANY);
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package org.cryptomator.ui.sharevault;
|
||||
|
||||
import dagger.BindsInstance;
|
||||
import dagger.Lazy;
|
||||
import dagger.Subcomponent;
|
||||
import org.cryptomator.common.vaults.Vault;
|
||||
import org.cryptomator.ui.common.FxmlFile;
|
||||
import org.cryptomator.ui.common.FxmlScene;
|
||||
|
||||
import javafx.scene.Scene;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
@ShareVaultScoped
|
||||
@Subcomponent(modules = {ShareVaultModule.class})
|
||||
public interface ShareVaultComponent {
|
||||
|
||||
@ShareVaultWindow
|
||||
Stage window();
|
||||
|
||||
@FxmlScene(FxmlFile.SHARE_VAULT)
|
||||
Lazy<Scene> scene();
|
||||
|
||||
default void showShareVaultWindow(){
|
||||
Stage stage = window();
|
||||
stage.setScene(scene().get());
|
||||
stage.show();
|
||||
}
|
||||
|
||||
@Subcomponent.Factory
|
||||
interface Factory {
|
||||
ShareVaultComponent create(@BindsInstance @ShareVaultWindow Vault vault);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
package org.cryptomator.ui.sharevault;
|
||||
|
||||
import dagger.Lazy;
|
||||
import org.cryptomator.common.vaults.Vault;
|
||||
import org.cryptomator.ui.common.FxController;
|
||||
import org.cryptomator.ui.keyloading.hub.HubKeyLoadingStrategy;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javafx.application.Application;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.stage.Stage;
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
@ShareVaultScoped
|
||||
public class ShareVaultController implements FxController {
|
||||
|
||||
private static final String SCHEME_PREFIX = "hub+";
|
||||
private static final String VISIT_HUB_URL = "https://cryptomator.org/hub/";
|
||||
private static final String BEST_PRACTICES_URL = "https://docs.cryptomator.org/en/latest/security/best-practices/#sharing-of-vaults";
|
||||
|
||||
private final Stage window;
|
||||
private final Lazy<Application> application;
|
||||
private final Vault vault;
|
||||
private final Boolean hubVault;
|
||||
|
||||
@Inject
|
||||
ShareVaultController(@ShareVaultWindow Stage window, //
|
||||
Lazy<Application> application, //
|
||||
@ShareVaultWindow Vault vault) {
|
||||
this.window = window;
|
||||
this.application = application;
|
||||
this.vault = vault;
|
||||
var vaultScheme = vault.getVaultConfigCache().getUnchecked().getKeyId().getScheme();
|
||||
this.hubVault = (vaultScheme.equals(HubKeyLoadingStrategy.SCHEME_HUB_HTTP) || vaultScheme.equals(HubKeyLoadingStrategy.SCHEME_HUB_HTTPS));
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void close() {
|
||||
window.close();
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void visitHub() {
|
||||
application.get().getHostServices().showDocument(VISIT_HUB_URL);
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void openHub() {
|
||||
application.get().getHostServices().showDocument(getHubUri(vault).toString());
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void visitBestPractices() {
|
||||
application.get().getHostServices().showDocument(BEST_PRACTICES_URL);
|
||||
}
|
||||
|
||||
private static URI getHubUri(Vault vault) {
|
||||
try {
|
||||
var keyID = new URI(vault.getVaultConfigCache().get().getKeyId().toString());
|
||||
assert keyID.getScheme().startsWith(SCHEME_PREFIX);
|
||||
return new URI(keyID.getScheme().substring(SCHEME_PREFIX.length()) + "://" + keyID.getHost() + "/app/vaults");
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
} catch (URISyntaxException e) {
|
||||
throw new IllegalStateException("URI constructed from params known to be valid", e);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isHubVault() {
|
||||
return hubVault;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package org.cryptomator.ui.sharevault;
|
||||
|
||||
import dagger.Binds;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import dagger.multibindings.IntoMap;
|
||||
import org.cryptomator.ui.common.DefaultSceneFactory;
|
||||
import org.cryptomator.ui.common.FxController;
|
||||
import org.cryptomator.ui.common.FxControllerKey;
|
||||
import org.cryptomator.ui.common.FxmlFile;
|
||||
import org.cryptomator.ui.common.FxmlLoaderFactory;
|
||||
import org.cryptomator.ui.common.FxmlScene;
|
||||
import org.cryptomator.ui.common.StageFactory;
|
||||
|
||||
import javax.inject.Provider;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.stage.Modality;
|
||||
import javafx.stage.Stage;
|
||||
import java.util.Map;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
@Module
|
||||
abstract class ShareVaultModule {
|
||||
|
||||
@Provides
|
||||
@ShareVaultWindow
|
||||
@ShareVaultScoped
|
||||
static FxmlLoaderFactory provideFxmlLoaderFactory(Map<Class<? extends FxController>, Provider<FxController>> factories, DefaultSceneFactory sceneFactory, ResourceBundle resourceBundle) {
|
||||
return new FxmlLoaderFactory(factories, sceneFactory, resourceBundle);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@ShareVaultWindow
|
||||
@ShareVaultScoped
|
||||
static Stage provideStage(StageFactory factory, ResourceBundle resourceBundle) {
|
||||
Stage stage = factory.create();
|
||||
stage.setResizable(false);
|
||||
stage.initModality(Modality.APPLICATION_MODAL);
|
||||
stage.setTitle(resourceBundle.getString("shareVault.title"));
|
||||
return stage;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@FxmlScene(FxmlFile.SHARE_VAULT)
|
||||
@ShareVaultScoped
|
||||
static Scene provideShareVaultScene(@ShareVaultWindow FxmlLoaderFactory fxmlLoaders) {
|
||||
return fxmlLoaders.createScene(FxmlFile.SHARE_VAULT);
|
||||
}
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@FxControllerKey(ShareVaultController.class)
|
||||
abstract FxController bindShareVaultController(ShareVaultController controller);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package org.cryptomator.ui.sharevault;
|
||||
|
||||
import javax.inject.Scope;
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
@Scope
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@interface ShareVaultScoped {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package org.cryptomator.ui.sharevault;
|
||||
|
||||
import javax.inject.Qualifier;
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
@Qualifier
|
||||
@Documented
|
||||
@Retention(RUNTIME)
|
||||
@interface ShareVaultWindow {
|
||||
|
||||
}
|
||||
@@ -936,3 +936,16 @@
|
||||
-fx-padding: 0.5px;
|
||||
-fx-background-color: CONTROL_BORDER_NORMAL;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* *
|
||||
* Ad box *
|
||||
* *
|
||||
******************************************************************************/
|
||||
|
||||
.ad-box {
|
||||
-fx-padding: 12px;
|
||||
-fx-background-color: CONTROL_BORDER_NORMAL, CONTROL_BG_NORMAL;
|
||||
-fx-background-insets: 0, 1px;
|
||||
-fx-background-radius: 4px;
|
||||
}
|
||||
@@ -935,3 +935,16 @@
|
||||
-fx-padding: 0.5px;
|
||||
-fx-background-color: CONTROL_BORDER_NORMAL;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* *
|
||||
* Ad box *
|
||||
* *
|
||||
******************************************************************************/
|
||||
|
||||
.ad-box {
|
||||
-fx-padding: 12px;
|
||||
-fx-background-color: CONTROL_BORDER_NORMAL, CONTROL_BG_NORMAL;
|
||||
-fx-background-insets: 0, 1px;
|
||||
-fx-background-radius: 4px;
|
||||
}
|
||||
108
src/main/resources/fxml/share_vault.fxml
Normal file
108
src/main/resources/fxml/share_vault.fxml
Normal file
@@ -0,0 +1,108 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.control.Button?>
|
||||
<?import javafx.scene.control.ButtonBar?>
|
||||
<?import javafx.scene.control.Label?>
|
||||
<?import javafx.scene.layout.Region?>
|
||||
<?import javafx.scene.layout.VBox?>
|
||||
<?import javafx.scene.layout.HBox?>
|
||||
<?import javafx.scene.layout.StackPane?>
|
||||
<?import javafx.scene.shape.Circle?>
|
||||
<?import org.cryptomator.ui.controls.FontAwesome5IconView?>
|
||||
<?import javafx.scene.image.ImageView?>
|
||||
<?import javafx.scene.image.Image?>
|
||||
<?import javafx.scene.control.Hyperlink?>
|
||||
<?import javafx.scene.control.Tooltip?>
|
||||
<?import javafx.scene.Group?>
|
||||
<HBox xmlns:fx="http://javafx.com/fxml"
|
||||
xmlns="http://javafx.com/javafx"
|
||||
fx:controller="org.cryptomator.ui.sharevault.ShareVaultController"
|
||||
prefWidth="540"
|
||||
spacing="12">
|
||||
<padding>
|
||||
<Insets topRightBottomLeft="12"/>
|
||||
</padding>
|
||||
<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>
|
||||
<VBox HBox.hgrow="ALWAYS" visible="${controller.hubVault}" managed="${controller.hubVault}">
|
||||
<Label text="%shareVault.hub.message" styleClass="label-large" wrapText="true">
|
||||
<padding>
|
||||
<Insets bottom="6" top="6"/>
|
||||
</padding>
|
||||
</Label>
|
||||
<Label text="%shareVault.hub.description" wrapText="true"/>
|
||||
<VBox>
|
||||
<padding>
|
||||
<Insets left="6"/>
|
||||
</padding>
|
||||
<Label text="%shareVault.hub.instruction.1" wrapText="true"/>
|
||||
<Label text="%shareVault.hub.instruction.2" wrapText="true"/>
|
||||
</VBox>
|
||||
</VBox>
|
||||
<VBox HBox.hgrow="ALWAYS" visible="${!controller.hubVault}" managed="${!controller.hubVault}">
|
||||
<Label text="%shareVault.message" styleClass="label-large" wrapText="true">
|
||||
<padding>
|
||||
<Insets bottom="6" top="6"/>
|
||||
</padding>
|
||||
</Label>
|
||||
<Label text="%shareVault.description" wrapText="true"/>
|
||||
<VBox>
|
||||
<padding>
|
||||
<Insets left="6"/>
|
||||
</padding>
|
||||
<Label text="%shareVault.instruction.1" wrapText="true"/>
|
||||
<Label text="%shareVault.instruction.2" wrapText="true"/>
|
||||
</VBox>
|
||||
<Region minHeight="6"/>
|
||||
<HBox spacing="6">
|
||||
<Hyperlink contentDisplay="GRAPHIC_ONLY" onAction="#visitBestPractices">
|
||||
<graphic>
|
||||
<FontAwesome5IconView glyph="QUESTION_CIRCLE" styleClass="glyph-icon-muted"/>
|
||||
</graphic>
|
||||
<tooltip>
|
||||
<Tooltip text="%shareVault.docsTooltip" showDelay="100ms"/>
|
||||
</tooltip>
|
||||
</Hyperlink>
|
||||
<Label text="%shareVault.remarkBestPractices" wrapText="true"/>
|
||||
</HBox>
|
||||
<Region minHeight="12"/>
|
||||
<HBox alignment="CENTER_LEFT" spacing="6" styleClass="ad-box">
|
||||
<VBox spacing="6" alignment="CENTER_LEFT">
|
||||
<ImageView HBox.hgrow="ALWAYS" fitWidth="180" preserveRatio="true" cache="true">
|
||||
<Image url="@../img/hub_logo.png"/>
|
||||
</ImageView>
|
||||
<Label text="%shareVault.hubAd.description" style="-fx-font-weight: bold;" wrapText="true"/>
|
||||
<VBox spacing="6" alignment="CENTER_LEFT">
|
||||
<padding>
|
||||
<Insets left="6"/>
|
||||
</padding>
|
||||
<Label text="%shareVault.hubAd.keyManagement" wrapText="true"/>
|
||||
<Label text="%shareVault.hubAd.authentication" wrapText="true"/>
|
||||
<Label text="%shareVault.hubAd.encryption" wrapText="true"/>
|
||||
</VBox>
|
||||
</VBox>
|
||||
<Region HBox.hgrow="ALWAYS"/>
|
||||
<ImageView HBox.hgrow="ALWAYS" fitWidth="180" preserveRatio="true" cache="true">
|
||||
<Image url="@../img/group-magic.png"/>
|
||||
</ImageView>
|
||||
</HBox>
|
||||
</VBox>
|
||||
<Region VBox.vgrow="ALWAYS" minHeight="18"/>
|
||||
<ButtonBar buttonMinWidth="120" buttonOrder="+CX">
|
||||
<buttons>
|
||||
<Button text="%generic.button.close" ButtonBar.buttonData="CANCEL_CLOSE" onAction="#close"/>
|
||||
<Button text="%shareVault.hub.openHub" ButtonBar.buttonData="NEXT_FORWARD" defaultButton="true" onAction="#openHub" visible="${controller.hubVault}" managed="${controller.hubVault}"/>
|
||||
<Button text="%shareVault.visitHub" ButtonBar.buttonData="NEXT_FORWARD" defaultButton="true" onAction="#visitHub" visible="${!controller.hubVault}" managed="${!controller.hubVault}"/>
|
||||
</buttons>
|
||||
</ButtonBar>
|
||||
</VBox>
|
||||
</HBox>
|
||||
@@ -24,14 +24,17 @@
|
||||
<FontAwesome5IconView glyph="KEY" glyphSize="15"/>
|
||||
</graphic>
|
||||
</Button>
|
||||
<Hyperlink text="%main.vaultDetail.passwordSavedInKeychain" visible="${controller.passwordSaved}" onAction="#showKeyVaultOptions">
|
||||
<Hyperlink text="%main.vaultDetail.passwordSavedInKeychain" visible="${controller.passwordSaved}" managed="${controller.passwordSaved}" onAction="#showKeyVaultOptions">
|
||||
<graphic>
|
||||
<FontAwesome5IconView glyph="LOCK"/>
|
||||
</graphic>
|
||||
</Hyperlink>
|
||||
|
||||
<Button text="%main.vaultDetail.share" minWidth="120" onAction="#share">
|
||||
<graphic>
|
||||
<FontAwesome5IconView glyph="SHARE" glyphSize="15"/>
|
||||
</graphic>
|
||||
</Button>
|
||||
<Region VBox.vgrow="ALWAYS"/>
|
||||
|
||||
<HBox alignment="BOTTOM_RIGHT">
|
||||
<Button text="%main.vaultDetail.optionsBtn" minWidth="120" onAction="#showVaultOptions">
|
||||
<graphic>
|
||||
|
||||
@@ -393,6 +393,7 @@ main.vaultDetail.unlockBtn=Unlock…
|
||||
main.vaultDetail.unlockNowBtn=Unlock Now
|
||||
main.vaultDetail.optionsBtn=Vault Options
|
||||
main.vaultDetail.passwordSavedInKeychain=Password saved
|
||||
main.vaultDetail.share=Share…
|
||||
### Unlocked
|
||||
main.vaultDetail.unlockedStatus=UNLOCKED
|
||||
main.vaultDetail.accessLocation=Your vault's contents are accessible here:
|
||||
@@ -530,4 +531,24 @@ updateReminder.message=Check for Updates?
|
||||
updateReminder.description=Stay updated with new features, bug fixes, and security improvements. We recommend to automatically check for updates.
|
||||
updateReminder.notNow=Not Now
|
||||
updateReminder.yesOnce=Yes, Once
|
||||
updateReminder.yesAutomatically=Yes, Automatically
|
||||
updateReminder.yesAutomatically=Yes, Automatically
|
||||
|
||||
# Share Vault
|
||||
shareVault.title=Share Vault
|
||||
shareVault.message=Would you like to share your vault with others?
|
||||
shareVault.description=Always be careful when sharing your vault with other people. In short, follow these steps:
|
||||
shareVault.instruction.1=1. Share access of the encrypted vault folder via cloud storage.
|
||||
shareVault.instruction.2=2. Share the vault password in a secure way.
|
||||
shareVault.remarkBestPractices=For more information, check out the best practices suggestions in our docs.
|
||||
shareVault.docsTooltip=Open the documentation to learn more about sharing of vaults.
|
||||
shareVault.hubAd.description=The secure way to work in teams
|
||||
shareVault.hubAd.keyManagement=• Zero-knowledge key management
|
||||
shareVault.hubAd.authentication=• Strong authentication
|
||||
shareVault.hubAd.encryption=• End-to-end encryption
|
||||
shareVault.visitHub=Visit Cryptomator Hub
|
||||
|
||||
shareVault.hub.message=How to share a Hub vault
|
||||
shareVault.hub.description=In order to share the vault content with another team member, you have to perform two steps:
|
||||
shareVault.hub.instruction.1=1. Share access of the encrypted vault folder via cloud storage.
|
||||
shareVault.hub.instruction.2=2. Grant access to team member in Cryptomator Hub.
|
||||
shareVault.hub.openHub=Open Cryptomator Hub
|
||||
BIN
src/main/resources/img/group-magic.png
Normal file
BIN
src/main/resources/img/group-magic.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 32 KiB |
BIN
src/main/resources/img/group-magic@2x.png
Normal file
BIN
src/main/resources/img/group-magic@2x.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 57 KiB |
BIN
src/main/resources/img/hub_logo.png
Normal file
BIN
src/main/resources/img/hub_logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 8.2 KiB |
BIN
src/main/resources/img/hub_logo@2x.png
Normal file
BIN
src/main/resources/img/hub_logo@2x.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
Reference in New Issue
Block a user