mirror of
https://github.com/cryptomator/cryptomator.git
synced 2026-05-18 02:31:27 +00:00
Merge branch 'develop' into feature/vault-format-8
[ci skip]
This commit is contained in:
26
.github/ISSUE_TEMPLATE/bug.md
vendored
26
.github/ISSUE_TEMPLATE/bug.md
vendored
@@ -5,28 +5,12 @@ labels: type:bug
|
||||
---
|
||||
|
||||
<!--
|
||||
**************************************
|
||||
* *
|
||||
* ⚠️⚠️⚠️ READ CAREFULLY ⚠️⚠️⚠️ *
|
||||
* *
|
||||
**************************************
|
||||
Do you want to ask a QUESTION? Are you looking for SUPPORT?
|
||||
We're happy to help you via our support channels! Please read: https://github.com/cryptomator/cryptomator/blob/develop/SUPPORT.md
|
||||
|
||||
By filing an issue, you are expected to comply with our code of conduct: https://github.com/cryptomator/cryptomator/blob/develop/.github/CODE_OF_CONDUCT.md
|
||||
|
||||
Of course, we also expect you to search for existing similar issues first! ;) https://github.com/cryptomator/cryptomator/issues?q=
|
||||
|
||||
Please make sure to:
|
||||
- Comply with our code of conduct: https://github.com/cryptomator/cryptomator/blob/develop/.github/CODE_OF_CONDUCT.md
|
||||
- Search for existing similar issues first: https://github.com/cryptomator/cryptomator/issues?q=
|
||||
|
||||
⚠️ IMPORTANT: If you don't stick to this template, the issue will get closed.
|
||||
|
||||
*****************************************************************************
|
||||
* *
|
||||
* To proof that you read this, please remove the X from the line below: *
|
||||
* *
|
||||
*****************************************************************************
|
||||
-->
|
||||
<!-- oooXooo -->
|
||||
|
||||
### Description
|
||||
|
||||
@@ -34,7 +18,7 @@ Of course, we also expect you to search for existing similar issues first! ;) ht
|
||||
|
||||
### System Setup
|
||||
|
||||
* Operating system and version: [Windows/macOS/Linux + Version]
|
||||
* Operating system and version: [Windows/macOS/Linux + Version ( + Desktop Environment, if Linux)]
|
||||
* Cryptomator version: [Shown in the settings]
|
||||
* Volume type: [Dokany/FUSE/WebDAV, shown in the settings]
|
||||
|
||||
@@ -61,7 +45,6 @@ Of course, we also expect you to search for existing similar issues first! ;) ht
|
||||
[Any additional information, log files, screenshots, configuration, or data that might be necessary to reproduce the issue.]
|
||||
|
||||
<!--
|
||||
|
||||
If you want to add the log file or screenshots, please add them as attachments. If your log file seems empty and doesn't show any errors, you may enable the debug mode first. Here is how to do that: https://community.cryptomator.org/t/how-do-i-enable-debug-mode/36
|
||||
|
||||
Then reproduce the problem to ensure all important information is contained in there. You may use test data or redact sensitive information from the log file.
|
||||
@@ -70,5 +53,4 @@ Log file location:
|
||||
- Windows: %appdata%/Cryptomator
|
||||
- macOS: ~/Library/Logs/Cryptomator
|
||||
- Linux: ~/.local/share/Cryptomator/logs
|
||||
|
||||
-->
|
||||
|
||||
8
.github/ISSUE_TEMPLATE/config.yml
vendored
8
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -1,8 +1,8 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Cryptomator Community
|
||||
- name: Help & Support
|
||||
url: https://community.cryptomator.org/
|
||||
about: Please ask and answer questions here
|
||||
- name: Documentation
|
||||
about: You will find answers in our community forum
|
||||
- name: User Manual
|
||||
url: https://docs.cryptomator.org/
|
||||
about: Get instructions on how to use Cryptomator
|
||||
about: Read the Cryptomator documentation here
|
||||
|
||||
13
.github/ISSUE_TEMPLATE/feature.md
vendored
13
.github/ISSUE_TEMPLATE/feature.md
vendored
@@ -5,14 +5,9 @@ labels: type:feature-request
|
||||
---
|
||||
|
||||
<!--
|
||||
|
||||
Do you want to ask a QUESTION? Are you looking for SUPPORT?
|
||||
We're happy to help you via our support channels! Please read: https://github.com/cryptomator/cryptomator/blob/develop/SUPPORT.md
|
||||
|
||||
By filing a feature request, you are expected to comply with our code of conduct: https://github.com/cryptomator/cryptomator/blob/develop/.github/CODE_OF_CONDUCT.md
|
||||
|
||||
Of course, we also expect you to search for existing similar feature requests first! ;)
|
||||
|
||||
Please make sure to:
|
||||
- Comply with our code of conduct: https://github.com/cryptomator/cryptomator/blob/develop/.github/CODE_OF_CONDUCT.md
|
||||
- Search for existing similar issues first: https://github.com/cryptomator/cryptomator/issues?q=
|
||||
-->
|
||||
|
||||
### Summary
|
||||
@@ -29,4 +24,4 @@ Of course, we also expect you to search for existing similar feature requests fi
|
||||
|
||||
### Additional Context
|
||||
|
||||
[Add any other context or screenshots about the feature request here.]
|
||||
[Add any other context or screenshots about the feature request here.]
|
||||
|
||||
0
SECURITY.md → .github/SECURITY.md
vendored
0
SECURITY.md → .github/SECURITY.md
vendored
0
SUPPORT.md → .github/SUPPORT.md
vendored
0
SUPPORT.md → .github/SUPPORT.md
vendored
30
.github/workflows/triageBugs.yml
vendored
30
.github/workflows/triageBugs.yml
vendored
@@ -6,20 +6,32 @@ on:
|
||||
|
||||
jobs:
|
||||
closeTemplateViolation:
|
||||
name: Close bug reports that violate the issue template
|
||||
name: Validate bug report against issue template
|
||||
runs-on: ubuntu-latest
|
||||
if: contains(github.event.issue.labels.*.name, 'type:bug')
|
||||
steps:
|
||||
- if: |
|
||||
contains(github.event.issue.labels.*.name, 'type:bug')
|
||||
&& (
|
||||
!contains(github.event.issue.body, '<!-- oooooo -->')
|
||||
|| !contains(github.event.issue.body, '### Description')
|
||||
)
|
||||
name: Close Issue
|
||||
- name: Check "Description"
|
||||
if: |
|
||||
!contains(github.event.issue.body, env.MUST_CONTAIN)
|
||||
|| contains(toJson(github.event.issue.body), env.MUST_NOT_CONTAIN)
|
||||
run: exit 1
|
||||
env:
|
||||
MUST_CONTAIN: '### Description'
|
||||
MUST_NOT_CONTAIN: '### Description\r\n\r\n[Summarize your problem.]\r\n\r\n### System Setup'
|
||||
- name: Check "Steps to Reproduce"
|
||||
if: |
|
||||
!contains(github.event.issue.body, env.MUST_CONTAIN)
|
||||
|| contains(toJson(github.event.issue.body), env.MUST_NOT_CONTAIN)
|
||||
run: exit 1
|
||||
env:
|
||||
MUST_CONTAIN: '### Steps to Reproduce'
|
||||
MUST_NOT_CONTAIN: '### Steps to Reproduce\r\n\r\n1. [First step]\r\n2. [Second step]\r\n3. [and so on…]\r\n\r\n#### Expected Behavior'
|
||||
- name: Close issue if one of the checks failed
|
||||
if: ${{ failure() }}
|
||||
uses: peter-evans/close-issue@v1
|
||||
with:
|
||||
comment: |
|
||||
This bug report did ignore our issue template. 😞
|
||||
Auto-closing this issue, since it is most likely not useful.
|
||||
|
||||
_This decision was made by a bot. If you think the bot is wrong, let us know and we'll reopen this issue._
|
||||
_This decision was made by a bot. If you think the bot is wrong, let us know and we'll reopen this issue._
|
||||
|
||||
2
.idea/runConfigurations/Cryptomator_Linux.xml
generated
2
.idea/runConfigurations/Cryptomator_Linux.xml
generated
@@ -2,7 +2,7 @@
|
||||
<configuration default="false" name="Cryptomator Linux" type="Application" factoryName="Application">
|
||||
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
|
||||
<module name="launcher" />
|
||||
<option name="VM_PARAMETERS" value="-Djdk.gtk.version=2 -Duser.language=en -Dcryptomator.settingsPath="~/.config/Cryptomator/settings.json" -Dcryptomator.ipcPortPath="~/.config/Cryptomator/ipcPort.bin" -Dcryptomator.logDir="~/.local/share/Cryptomator/logs" -Dcryptomator.mountPointsDir="~/.local/share/Cryptomator/mnt" -Xss20m -Xmx512m" />
|
||||
<option name="VM_PARAMETERS" value="-Djdk.gtk.version=2 -Duser.language=en -Dcryptomator.settingsPath="~/.config/Cryptomator/settings.json" -Dcryptomator.ipcPortPath="~/.config/Cryptomator/ipcPort.bin" -Dcryptomator.logDir="~/.local/share/Cryptomator/logs" -Dcryptomator.mountPointsDir="~/.local/share/Cryptomator/mnt" -Dcryptomator.showTrayIcon=true -Xss20m -Xmx512m" />
|
||||
<method v="2">
|
||||
<option name="Make" enabled="true" />
|
||||
</method>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<configuration default="false" name="Cryptomator Linux Dev" type="Application" factoryName="Application">
|
||||
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
|
||||
<module name="launcher" />
|
||||
<option name="VM_PARAMETERS" value="-Djdk.gtk.version=2 -Duser.language=en -Dcryptomator.settingsPath="~/.config/Cryptomator-Dev/settings.json" -Dcryptomator.ipcPortPath="~/.config/Cryptomator-Dev/ipcPort.bin" -Dcryptomator.logDir="~/.local/share/Cryptomator-Dev/logs" -Dcryptomator.mountPointsDir="~/.local/share/Cryptomator-Dev/mnt" -Dfuse.experimental="true" -Xss20m -Xmx512m" />
|
||||
<option name="VM_PARAMETERS" value="-Djdk.gtk.version=2 -Duser.language=en -Dcryptomator.settingsPath="~/.config/Cryptomator-Dev/settings.json" -Dcryptomator.ipcPortPath="~/.config/Cryptomator-Dev/ipcPort.bin" -Dcryptomator.logDir="~/.local/share/Cryptomator-Dev/logs" -Dcryptomator.mountPointsDir="~/.local/share/Cryptomator-Dev/mnt" -Dcryptomator.showTrayIcon=true -Dfuse.experimental="true" -Xss20m -Xmx512m" />
|
||||
<method v="2">
|
||||
<option name="Make" enabled="true" />
|
||||
</method>
|
||||
|
||||
2
.idea/runConfigurations/Cryptomator_Windows.xml
generated
2
.idea/runConfigurations/Cryptomator_Windows.xml
generated
@@ -2,7 +2,7 @@
|
||||
<configuration default="false" name="Cryptomator Windows" type="Application" factoryName="Application">
|
||||
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
|
||||
<module name="launcher" />
|
||||
<option name="VM_PARAMETERS" value="-Duser.language=en -Dcryptomator.settingsPath="~/AppData/Roaming/Cryptomator/settings.json" -Dcryptomator.ipcPortPath="~/AppData/Roaming/Cryptomator/ipcPort.bin" -Dcryptomator.logDir="~/AppData/Roaming/Cryptomator" -Dcryptomator.keychainPath="~/AppData/Roaming/Cryptomator/keychain.json" -Dcryptomator.mountPointsDir="~/Cryptomator" -Xss2m -Xmx512m" />
|
||||
<option name="VM_PARAMETERS" value="-Duser.language=en -Dcryptomator.settingsPath="~/AppData/Roaming/Cryptomator/settings.json" -Dcryptomator.ipcPortPath="~/AppData/Roaming/Cryptomator/ipcPort.bin" -Dcryptomator.logDir="~/AppData/Roaming/Cryptomator" -Dcryptomator.keychainPath="~/AppData/Roaming/Cryptomator/keychain.json" -Dcryptomator.mountPointsDir="~/Cryptomator" -Dcryptomator.showTrayIcon=true -Xss2m -Xmx512m" />
|
||||
<method v="2">
|
||||
<option name="Make" enabled="true" />
|
||||
</method>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<configuration default="false" name="Cryptomator Windows Dev" type="Application" factoryName="Application">
|
||||
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
|
||||
<module name="launcher" />
|
||||
<option name="VM_PARAMETERS" value="-Duser.language=en -Dcryptomator.settingsPath="~/AppData/Roaming/Cryptomator-Dev/settings.json" -Dcryptomator.ipcPortPath="~/AppData/Roaming/Cryptomator-Dev/ipcPort.bin" -Dcryptomator.logDir="~/AppData/Roaming/Cryptomator-Dev" -Dcryptomator.keychainPath="~/AppData/Roaming/Cryptomator-Dev/keychain.json" -Dcryptomator.mountPointsDir="~/Cryptomator-Dev" -Dfuse.experimental="true" -Xss2m -Xmx512m" />
|
||||
<option name="VM_PARAMETERS" value="-Duser.language=en -Dcryptomator.settingsPath="~/AppData/Roaming/Cryptomator-Dev/settings.json" -Dcryptomator.ipcPortPath="~/AppData/Roaming/Cryptomator-Dev/ipcPort.bin" -Dcryptomator.logDir="~/AppData/Roaming/Cryptomator-Dev" -Dcryptomator.keychainPath="~/AppData/Roaming/Cryptomator-Dev/keychain.json" -Dcryptomator.mountPointsDir="~/Cryptomator-Dev" -Dfuse.experimental="true" -Dcryptomator.showTrayIcon=true -Xss2m -Xmx512m" />
|
||||
<method v="2">
|
||||
<option name="Make" enabled="true" />
|
||||
</method>
|
||||
|
||||
2
.idea/runConfigurations/Cryptomator_macOS.xml
generated
2
.idea/runConfigurations/Cryptomator_macOS.xml
generated
@@ -5,7 +5,7 @@
|
||||
</envs>
|
||||
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
|
||||
<module name="launcher" />
|
||||
<option name="VM_PARAMETERS" value="-Duser.language=en -Dcryptomator.settingsPath="~/Library/Application Support/Cryptomator/settings.json" -Dcryptomator.ipcPortPath="~/Library/Application Support/Cryptomator/ipcPort.bin" -Dcryptomator.logDir="~/Library/Logs/Cryptomator" -Xss2m -Xmx512m -ea" />
|
||||
<option name="VM_PARAMETERS" value="-Duser.language=en -Dcryptomator.settingsPath="~/Library/Application Support/Cryptomator/settings.json" -Dcryptomator.ipcPortPath="~/Library/Application Support/Cryptomator/ipcPort.bin" -Dcryptomator.logDir="~/Library/Logs/Cryptomator" -Dcryptomator.showTrayIcon=true -Xss2m -Xmx512m -ea" />
|
||||
<method v="2">
|
||||
<option name="Make" enabled="true" />
|
||||
</method>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
</envs>
|
||||
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
|
||||
<module name="launcher" />
|
||||
<option name="VM_PARAMETERS" value="-Duser.language=en -Dcryptomator.settingsPath="~/Library/Application Support/Cryptomator-Dev/settings.json" -Dcryptomator.ipcPortPath="~/Library/Application Support/Cryptomator-Dev/ipcPort.bin" -Dcryptomator.logDir="~/Library/Logs/Cryptomator-Dev" -Xss2m -Xmx512m -ea" />
|
||||
<option name="VM_PARAMETERS" value="-Duser.language=en -Dcryptomator.settingsPath="~/Library/Application Support/Cryptomator-Dev/settings.json" -Dcryptomator.ipcPortPath="~/Library/Application Support/Cryptomator-Dev/ipcPort.bin" -Dcryptomator.logDir="~/Library/Logs/Cryptomator-Dev" -Dcryptomator.showTrayIcon=true -Xss2m -Xmx512m -ea" />
|
||||
<method v="2">
|
||||
<option name="Make" enabled="true" />
|
||||
</method>
|
||||
|
||||
@@ -21,14 +21,13 @@ import java.util.stream.StreamSupport;
|
||||
public class Environment {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(Environment.class);
|
||||
private static final String USER_HOME = System.getProperty("user.home");
|
||||
private static final Path RELATIVE_HOME_DIR = Paths.get("~");
|
||||
private static final Path ABSOLUTE_HOME_DIR = Paths.get(USER_HOME);
|
||||
private static final char PATH_LIST_SEP = ':';
|
||||
private static final int DEFAULT_MIN_PW_LENGTH = 8;
|
||||
|
||||
@Inject
|
||||
public Environment() {
|
||||
LOG.debug("user.home: {}", System.getProperty("user.home"));
|
||||
LOG.debug("java.library.path: {}", System.getProperty("java.library.path"));
|
||||
LOG.debug("user.language: {}", System.getProperty("user.language"));
|
||||
LOG.debug("user.region: {}", System.getProperty("user.region"));
|
||||
@@ -40,6 +39,7 @@ public class Environment {
|
||||
LOG.debug("cryptomator.mountPointsDir: {}", System.getProperty("cryptomator.mountPointsDir"));
|
||||
LOG.debug("cryptomator.minPwLength: {}", System.getProperty("cryptomator.minPwLength"));
|
||||
LOG.debug("cryptomator.buildNumber: {}", System.getProperty("cryptomator.buildNumber"));
|
||||
LOG.debug("cryptomator.showTrayIcon: {}", System.getProperty("cryptomator.showTrayIcon"));
|
||||
LOG.debug("fuse.experimental: {}", Boolean.getBoolean("fuse.experimental"));
|
||||
}
|
||||
|
||||
@@ -75,6 +75,11 @@ public class Environment {
|
||||
return getInt("cryptomator.minPwLength", DEFAULT_MIN_PW_LENGTH);
|
||||
}
|
||||
|
||||
public boolean showTrayIcon() {
|
||||
return Boolean.getBoolean("cryptomator.showTrayIcon");
|
||||
}
|
||||
|
||||
@Deprecated // TODO: remove as soon as custom mount path works properly on Win+Fuse
|
||||
public boolean useExperimentalFuse() {
|
||||
return Boolean.getBoolean("fuse.experimental");
|
||||
}
|
||||
@@ -92,8 +97,13 @@ public class Environment {
|
||||
String value = System.getProperty(propertyName);
|
||||
return Optional.ofNullable(value).map(Paths::get);
|
||||
}
|
||||
// visible for testing
|
||||
|
||||
// visible for testing
|
||||
Path getHomeDir() {
|
||||
return getPath("user.home").orElseThrow();
|
||||
}
|
||||
|
||||
// visible for testing
|
||||
Stream<Path> getPaths(String propertyName) {
|
||||
Stream<String> rawSettingsPaths = getRawList(propertyName, PATH_LIST_SEP);
|
||||
return rawSettingsPaths.filter(Predicate.not(Strings::isNullOrEmpty)).map(Paths::get).map(this::replaceHomeDir);
|
||||
@@ -101,7 +111,7 @@ public class Environment {
|
||||
|
||||
private Path replaceHomeDir(Path path) {
|
||||
if (path.startsWith(RELATIVE_HOME_DIR)) {
|
||||
return ABSOLUTE_HOME_DIR.resolve(RELATIVE_HOME_DIR.relativize(path));
|
||||
return getHomeDir().resolve(RELATIVE_HOME_DIR.relativize(path));
|
||||
} else {
|
||||
return path;
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
package org.cryptomator.common.settings;
|
||||
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
import org.cryptomator.common.Environment;
|
||||
|
||||
import javafx.beans.Observable;
|
||||
import javafx.beans.property.BooleanProperty;
|
||||
@@ -39,7 +40,8 @@ public class Settings {
|
||||
public static final UiTheme DEFAULT_THEME = UiTheme.LIGHT;
|
||||
public static final KeychainBackend DEFAULT_KEYCHAIN_BACKEND = SystemUtils.IS_OS_WINDOWS ? KeychainBackend.WIN_SYSTEM_KEYCHAIN : SystemUtils.IS_OS_MAC ? KeychainBackend.MAC_SYSTEM_KEYCHAIN : KeychainBackend.GNOME;
|
||||
public static final NodeOrientation DEFAULT_USER_INTERFACE_ORIENTATION = NodeOrientation.LEFT_TO_RIGHT;
|
||||
private static final String DEFAULT_LICENSE_KEY = "";
|
||||
public static final String DEFAULT_LICENSE_KEY = "";
|
||||
public static final boolean DEFAULT_SHOW_MINIMIZE_BUTTON = false;
|
||||
|
||||
private final ObservableList<VaultSettings> directories = FXCollections.observableArrayList(VaultSettings::observables);
|
||||
private final BooleanProperty askedForUpdateCheck = new SimpleBooleanProperty(DEFAULT_ASKED_FOR_UPDATE_CHECK);
|
||||
@@ -54,13 +56,17 @@ public class Settings {
|
||||
private final ObjectProperty<KeychainBackend> keychainBackend = new SimpleObjectProperty<>(DEFAULT_KEYCHAIN_BACKEND);
|
||||
private final ObjectProperty<NodeOrientation> userInterfaceOrientation = new SimpleObjectProperty<>(DEFAULT_USER_INTERFACE_ORIENTATION);
|
||||
private final StringProperty licenseKey = new SimpleStringProperty(DEFAULT_LICENSE_KEY);
|
||||
private final BooleanProperty showMinimizeButton = new SimpleBooleanProperty(DEFAULT_SHOW_MINIMIZE_BUTTON);
|
||||
private final BooleanProperty showTrayIcon;
|
||||
|
||||
private Consumer<Settings> saveCmd;
|
||||
|
||||
/**
|
||||
* Package-private constructor; use {@link SettingsProvider}.
|
||||
*/
|
||||
Settings() {
|
||||
Settings(Environment env) {
|
||||
this.showTrayIcon = new SimpleBooleanProperty(env.showTrayIcon());
|
||||
|
||||
directories.addListener(this::somethingChanged);
|
||||
askedForUpdateCheck.addListener(this::somethingChanged);
|
||||
checkForUpdates.addListener(this::somethingChanged);
|
||||
@@ -74,6 +80,8 @@ public class Settings {
|
||||
keychainBackend.addListener(this::somethingChanged);
|
||||
userInterfaceOrientation.addListener(this::somethingChanged);
|
||||
licenseKey.addListener(this::somethingChanged);
|
||||
showMinimizeButton.addListener(this::somethingChanged);
|
||||
showTrayIcon.addListener(this::somethingChanged);
|
||||
}
|
||||
|
||||
void setSaveCmd(Consumer<Settings> saveCmd) {
|
||||
@@ -141,4 +149,12 @@ public class Settings {
|
||||
public StringProperty licenseKey() {
|
||||
return licenseKey;
|
||||
}
|
||||
|
||||
public BooleanProperty showMinimizeButton() {
|
||||
return showMinimizeButton;
|
||||
}
|
||||
|
||||
public BooleanProperty showTrayIcon() {
|
||||
return showTrayIcon;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,19 +9,29 @@ import com.google.gson.TypeAdapter;
|
||||
import com.google.gson.stream.JsonReader;
|
||||
import com.google.gson.stream.JsonToken;
|
||||
import com.google.gson.stream.JsonWriter;
|
||||
import org.cryptomator.common.Environment;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import javafx.geometry.NodeOrientation;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Singleton
|
||||
public class SettingsJsonAdapter extends TypeAdapter<Settings> {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(SettingsJsonAdapter.class);
|
||||
|
||||
private final VaultSettingsJsonAdapter vaultSettingsJsonAdapter = new VaultSettingsJsonAdapter();
|
||||
private final Environment env;
|
||||
|
||||
@Inject
|
||||
public SettingsJsonAdapter(Environment env) {
|
||||
this.env = env;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(JsonWriter out, Settings value) throws IOException {
|
||||
@@ -40,6 +50,8 @@ public class SettingsJsonAdapter extends TypeAdapter<Settings> {
|
||||
out.name("uiOrientation").value(value.userInterfaceOrientation().get().name());
|
||||
out.name("keychainBackend").value(value.keychainBackend().get().name());
|
||||
out.name("licenseKey").value(value.licenseKey().get());
|
||||
out.name("showMinimizeButton").value(value.showMinimizeButton().get());
|
||||
out.name("showTrayIcon").value(value.showTrayIcon().get());
|
||||
out.endObject();
|
||||
}
|
||||
|
||||
@@ -53,7 +65,7 @@ public class SettingsJsonAdapter extends TypeAdapter<Settings> {
|
||||
|
||||
@Override
|
||||
public Settings read(JsonReader in) throws IOException {
|
||||
Settings settings = new Settings();
|
||||
Settings settings = new Settings(env);
|
||||
|
||||
in.beginObject();
|
||||
while (in.hasNext()) {
|
||||
@@ -72,6 +84,8 @@ public class SettingsJsonAdapter extends TypeAdapter<Settings> {
|
||||
case "uiOrientation" -> settings.userInterfaceOrientation().set(parseUiOrientation(in.nextString()));
|
||||
case "keychainBackend" -> settings.keychainBackend().set(parseKeychainBackend(in.nextString()));
|
||||
case "licenseKey" -> settings.licenseKey().set(in.nextString());
|
||||
case "showMinimizeButton" -> settings.showMinimizeButton().set(in.nextBoolean());
|
||||
case "showTrayIcon" -> settings.showTrayIcon().set(in.nextBoolean());
|
||||
default -> {
|
||||
LOG.warn("Unsupported vault setting found in JSON: " + name);
|
||||
in.skipValue();
|
||||
@@ -137,5 +151,4 @@ public class SettingsJsonAdapter extends TypeAdapter<Settings> {
|
||||
in.endArray();
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -49,13 +49,14 @@ public class SettingsProvider implements Supplier<Settings> {
|
||||
|
||||
private final AtomicReference<ScheduledFuture<?>> scheduledSaveCmd = new AtomicReference<>();
|
||||
private final Supplier<Settings> settings = Suppliers.memoize(this::load);
|
||||
private final SettingsJsonAdapter settingsJsonAdapter = new SettingsJsonAdapter();
|
||||
private final SettingsJsonAdapter settingsJsonAdapter;
|
||||
private final Environment env;
|
||||
private final ScheduledExecutorService scheduler;
|
||||
private final Gson gson;
|
||||
|
||||
@Inject
|
||||
public SettingsProvider(Environment env, ScheduledExecutorService scheduler) {
|
||||
public SettingsProvider(SettingsJsonAdapter settingsJsonAdapter, Environment env, ScheduledExecutorService scheduler) {
|
||||
this.settingsJsonAdapter = settingsJsonAdapter;
|
||||
this.env = env;
|
||||
this.scheduler = scheduler;
|
||||
this.gson = new GsonBuilder() //
|
||||
@@ -70,7 +71,7 @@ public class SettingsProvider implements Supplier<Settings> {
|
||||
}
|
||||
|
||||
private Settings load() {
|
||||
Settings settings = env.getSettingsPath().flatMap(this::tryLoad).findFirst().orElse(new Settings());
|
||||
Settings settings = env.getSettingsPath().flatMap(this::tryLoad).findFirst().orElse(new Settings(env));
|
||||
settings.setSaveCmd(this::scheduleSave);
|
||||
return settings;
|
||||
}
|
||||
@@ -90,7 +91,7 @@ public class SettingsProvider implements Supplier<Settings> {
|
||||
}
|
||||
} catch (NoSuchFileException e) {
|
||||
return Stream.empty();
|
||||
} catch (IOException e) {
|
||||
} catch (IOException | JsonParseException e) {
|
||||
LOG.warn("Exception while loading settings from " + path, e);
|
||||
return Stream.empty();
|
||||
}
|
||||
|
||||
@@ -71,10 +71,14 @@ public class DokanyVolume extends AbstractVolume {
|
||||
|
||||
@Override
|
||||
public void unmountForced() {
|
||||
mount.close(); //TODO: with next dokany-nio-release, change this to unmountForced()
|
||||
mount.unmountForced();
|
||||
cleanupMountPoint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsForcedUnmount() {
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public boolean isSupported() {
|
||||
return DokanyVolume.isSupportedStatic();
|
||||
|
||||
@@ -106,7 +106,7 @@ public class Vault {
|
||||
if (vaultSettings.usesReadOnlyMode().get()) {
|
||||
flags.add(FileSystemFlags.READONLY);
|
||||
}
|
||||
if (vaultSettings.filenameLengthLimit().get() == -1) {
|
||||
if (!flags.contains(FileSystemFlags.READONLY) && vaultSettings.filenameLengthLimit().get() == -1) {
|
||||
LOG.debug("Determining file name length limitations...");
|
||||
int limit = new FileSystemCapabilityChecker().determineSupportedFileNameLength(getPath());
|
||||
vaultSettings.filenameLengthLimit().set(limit);
|
||||
@@ -126,12 +126,28 @@ public class Vault {
|
||||
}
|
||||
}
|
||||
|
||||
private void destroyCryptoFileSystem() {
|
||||
CryptoFileSystem fs = cryptoFileSystem.getAndSet(null);
|
||||
if (fs != null) {
|
||||
try {
|
||||
fs.close();
|
||||
} catch (IOException e) {
|
||||
LOG.error("Error closing file system.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void unlock(CharSequence passphrase) throws CryptoException, IOException, VolumeException, InvalidMountPointException {
|
||||
if (cryptoFileSystem.get() == null) {
|
||||
CryptoFileSystem fs = createCryptoFileSystem(passphrase);
|
||||
cryptoFileSystem.set(fs);
|
||||
volume = volumeProvider.get();
|
||||
volume.mount(fs, getEffectiveMountFlags());
|
||||
try {
|
||||
volume = volumeProvider.get();
|
||||
volume.mount(fs, getEffectiveMountFlags());
|
||||
} catch (IOException | InvalidMountPointException | VolumeException e) {
|
||||
destroyCryptoFileSystem();
|
||||
throw e;
|
||||
}
|
||||
} else {
|
||||
throw new IllegalStateException("Already unlocked.");
|
||||
}
|
||||
@@ -143,14 +159,7 @@ public class Vault {
|
||||
} else {
|
||||
volume.unmount();
|
||||
}
|
||||
CryptoFileSystem fs = cryptoFileSystem.getAndSet(null);
|
||||
if (fs != null) {
|
||||
try {
|
||||
fs.close();
|
||||
} catch (IOException e) {
|
||||
LOG.error("Error closing file system.", e);
|
||||
}
|
||||
}
|
||||
destroyCryptoFileSystem();
|
||||
}
|
||||
|
||||
public void reveal() throws VolumeException {
|
||||
|
||||
@@ -156,7 +156,7 @@ public class VaultModule {
|
||||
//See: https://github.com/billziss-gh/winfsp/issues/319
|
||||
if (!readOnly.get()) {
|
||||
flags.append(" -ouid=-1");
|
||||
flags.append(" -ogid=-1");
|
||||
flags.append(" -ogid=11");
|
||||
}
|
||||
flags.append(" -ovolname=").append('"').append(mountName.get()).append('"');
|
||||
//Dokany requires this option to be set, WinFSP doesn't seem to share this peculiarity,
|
||||
|
||||
@@ -8,6 +8,7 @@ import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
@@ -20,14 +21,10 @@ class EnvironmentTest {
|
||||
|
||||
private Environment env;
|
||||
|
||||
@BeforeAll
|
||||
static void init() {
|
||||
System.setProperty("user.home", "/home/testuser");
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
void initEach() {
|
||||
env = new Environment();
|
||||
void init() {
|
||||
env = Mockito.spy(new Environment());
|
||||
Mockito.when(env.getHomeDir()).thenReturn(Path.of("/home/testuser"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -5,16 +5,19 @@
|
||||
*******************************************************************************/
|
||||
package org.cryptomator.common.settings;
|
||||
|
||||
import org.cryptomator.common.Environment;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class SettingsJsonAdapterTest {
|
||||
|
||||
private final SettingsJsonAdapter adapter = new SettingsJsonAdapter();
|
||||
private final Environment env = Mockito.mock(Environment.class);
|
||||
private final SettingsJsonAdapter adapter = new SettingsJsonAdapter(env);
|
||||
|
||||
@Test
|
||||
public void testDeserialize() throws IOException {
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
*******************************************************************************/
|
||||
package org.cryptomator.common.settings;
|
||||
|
||||
import org.cryptomator.common.Environment;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
@@ -14,8 +15,10 @@ public class SettingsTest {
|
||||
|
||||
@Test
|
||||
public void testAutoSave() {
|
||||
Environment env = Mockito.mock(Environment.class);
|
||||
@SuppressWarnings("unchecked") Consumer<Settings> changeListener = Mockito.mock(Consumer.class);
|
||||
Settings settings = new Settings();
|
||||
|
||||
Settings settings = new Settings(env);
|
||||
settings.setSaveCmd(changeListener);
|
||||
VaultSettings vaultSettings = VaultSettings.withRandomId();
|
||||
Mockito.verify(changeListener, Mockito.times(0)).accept(settings);
|
||||
|
||||
41
main/pom.xml
41
main/pom.xml
@@ -26,12 +26,12 @@
|
||||
<!-- cryptomator dependencies -->
|
||||
<cryptomator.cryptofs.version>2.0.0-beta1</cryptomator.cryptofs.version>
|
||||
<cryptomator.integrations.version>0.1.6</cryptomator.integrations.version>
|
||||
<cryptomator.integrations.win.version>0.1.0-beta1</cryptomator.integrations.win.version>
|
||||
<cryptomator.integrations.win.version>0.2.1</cryptomator.integrations.win.version>
|
||||
<cryptomator.integrations.mac.version>0.1.0-beta3</cryptomator.integrations.mac.version>
|
||||
<cryptomator.integrations.linux.version>0.1.0-beta2</cryptomator.integrations.linux.version>
|
||||
<cryptomator.fuse.version>1.2.5</cryptomator.fuse.version>
|
||||
<cryptomator.dokany.version>1.2.0</cryptomator.dokany.version>
|
||||
<cryptomator.webdav.version>1.0.13</cryptomator.webdav.version>
|
||||
<cryptomator.fuse.version>1.2.6</cryptomator.fuse.version>
|
||||
<cryptomator.dokany.version>1.2.1</cryptomator.dokany.version>
|
||||
<cryptomator.webdav.version>1.0.14</cryptomator.webdav.version>
|
||||
|
||||
<!-- 3rd party dependencies -->
|
||||
<javafx.version>15</javafx.version>
|
||||
@@ -230,6 +230,13 @@
|
||||
<version>${javafx.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- TODO: temporary fix for XXE attack, can be removed once java-jwt is updated -->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>2.10.5.1</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
@@ -332,6 +339,32 @@
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>dependency-check</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.owasp</groupId>
|
||||
<artifactId>dependency-check-maven</artifactId>
|
||||
<version>6.0.3</version>
|
||||
<configuration>
|
||||
<cveValidForHours>24</cveValidForHours>
|
||||
<failBuildOnCVSS>0</failBuildOnCVSS>
|
||||
<skipTestScope>true</skipTestScope>
|
||||
<detail>true</detail>
|
||||
<suppressionFile>suppression.xml</suppressionFile>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>check</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
<build>
|
||||
|
||||
19
main/suppression.xml
Normal file
19
main/suppression.xml
Normal file
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- This file lists false positives found by org.owasp:dependency-check-maven build plugin -->
|
||||
<suppressions xmlns="https://jeremylong.github.io/DependencyCheck/dependency-suppression.1.2.xsd">
|
||||
<suppress>
|
||||
<notes><![CDATA[ Upstream fix backported from 2.11.0 to 2.10.5.1, see https://github.com/FasterXML/jackson-databind/issues/2589#issuecomment-714833837. ]]></notes>
|
||||
<gav>com.fasterxml.jackson.core:jackson-databind:2.10.5.1</gav>
|
||||
<cve>CVE-2020-25649</cve>
|
||||
</suppress>
|
||||
<suppress>
|
||||
<notes><![CDATA[ Suppress known vulnerabilities in FUSE libraries for fuse-nio-adapter. For more info, see suppression.xml of https://github.com/cryptomator/fuse-nio-adapter ]]></notes>
|
||||
<gav regex="true">^org\.cryptomator:fuse-nio-adapter:.*$</gav>
|
||||
<cvssBelow>9</cvssBelow>
|
||||
</suppress>
|
||||
<suppress>
|
||||
<notes><![CDATA[ Suppress known vulnerabilities in FUSE libraries for jnr-fuse (dependency of fuse-nio-adapter). ]]></notes>
|
||||
<gav regex="true">^com\.github\.serceman:jnr-fuse:.*$</gav>
|
||||
<cvssBelow>9</cvssBelow>
|
||||
</suppress>
|
||||
</suppressions>
|
||||
@@ -11,6 +11,8 @@ public enum FxmlFile {
|
||||
CHANGEPASSWORD("/fxml/changepassword.fxml"), //
|
||||
ERROR("/fxml/error.fxml"), //
|
||||
FORGET_PASSWORD("/fxml/forget_password.fxml"), //
|
||||
LOCK_FORCED("/fxml/lock_forced.fxml"), //
|
||||
LOCK_FAILED("/fxml/lock_failed.fxml"), //
|
||||
MAIN_WINDOW("/fxml/main_window.fxml"), //
|
||||
MIGRATION_CAPABILITY_ERROR("/fxml/migration_capability_error.fxml"), //
|
||||
MIGRATION_IMPOSSIBLE("/fxml/migration_impossible.fxml"),
|
||||
|
||||
@@ -65,6 +65,7 @@ public class VaultService {
|
||||
public Task<Vault> createLockTask(Vault vault, boolean forced) {
|
||||
Task<Vault> task = new LockVaultTask(vault, forced);
|
||||
task.setOnSucceeded(evt -> LOG.info("Locked {}", vault.getDisplayName()));
|
||||
task.setOnFailed(evt -> LOG.info("Failed to lock {}.", vault.getDisplayName(), evt.getSource().getException()));
|
||||
return task;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import org.cryptomator.integrations.uiappearance.UiAppearanceException;
|
||||
import org.cryptomator.integrations.uiappearance.UiAppearanceListener;
|
||||
import org.cryptomator.integrations.uiappearance.UiAppearanceProvider;
|
||||
import org.cryptomator.ui.common.VaultService;
|
||||
import org.cryptomator.ui.lock.LockComponent;
|
||||
import org.cryptomator.ui.mainwindow.MainWindowComponent;
|
||||
import org.cryptomator.ui.preferences.PreferencesComponent;
|
||||
import org.cryptomator.ui.preferences.SelectedPreferencesTab;
|
||||
@@ -31,6 +32,8 @@ import javafx.stage.Stage;
|
||||
import javafx.stage.Window;
|
||||
import java.awt.desktop.QuitResponse;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.CompletionStage;
|
||||
|
||||
@FxApplicationScoped
|
||||
public class FxApplication extends Application {
|
||||
@@ -42,6 +45,7 @@ public class FxApplication extends Application {
|
||||
private final Lazy<PreferencesComponent> preferencesWindow;
|
||||
private final Lazy<QuitComponent> quitWindow;
|
||||
private final Provider<UnlockComponent.Builder> unlockWindowBuilderProvider;
|
||||
private final Provider<LockComponent.Builder> lockWindowBuilderProvider;
|
||||
private final Optional<TrayIntegrationProvider> trayIntegration;
|
||||
private final Optional<UiAppearanceProvider> appearanceProvider;
|
||||
private final VaultService vaultService;
|
||||
@@ -51,11 +55,12 @@ public class FxApplication extends Application {
|
||||
private final UiAppearanceListener systemInterfaceThemeListener = this::systemInterfaceThemeChanged;
|
||||
|
||||
@Inject
|
||||
FxApplication(Settings settings, Lazy<MainWindowComponent> mainWindow, Lazy<PreferencesComponent> preferencesWindow, Provider<UnlockComponent.Builder> unlockWindowBuilderProvider, Lazy<QuitComponent> quitWindow, Optional<TrayIntegrationProvider> trayIntegration, Optional<UiAppearanceProvider> appearanceProvider, VaultService vaultService, LicenseHolder licenseHolder) {
|
||||
FxApplication(Settings settings, Lazy<MainWindowComponent> mainWindow, Lazy<PreferencesComponent> preferencesWindow, Provider<UnlockComponent.Builder> unlockWindowBuilderProvider, Provider<LockComponent.Builder> lockWindowBuilderProvider, Lazy<QuitComponent> quitWindow, Optional<TrayIntegrationProvider> trayIntegration, Optional<UiAppearanceProvider> appearanceProvider, VaultService vaultService, LicenseHolder licenseHolder) {
|
||||
this.settings = settings;
|
||||
this.mainWindow = mainWindow;
|
||||
this.preferencesWindow = preferencesWindow;
|
||||
this.unlockWindowBuilderProvider = unlockWindowBuilderProvider;
|
||||
this.lockWindowBuilderProvider = lockWindowBuilderProvider;
|
||||
this.quitWindow = quitWindow;
|
||||
this.trayIntegration = trayIntegration;
|
||||
this.appearanceProvider = appearanceProvider;
|
||||
@@ -96,11 +101,14 @@ public class FxApplication extends Application {
|
||||
});
|
||||
}
|
||||
|
||||
public void showMainWindow() {
|
||||
public CompletionStage<Stage> showMainWindow() {
|
||||
CompletableFuture<Stage> future = new CompletableFuture<>();
|
||||
Platform.runLater(() -> {
|
||||
mainWindow.get().showMainWindow();
|
||||
var win = mainWindow.get().showMainWindow();
|
||||
LOG.debug("Showing MainWindow");
|
||||
future.complete(win);
|
||||
});
|
||||
return future;
|
||||
}
|
||||
|
||||
public void startUnlockWorkflow(Vault vault, Optional<Stage> owner) {
|
||||
@@ -110,6 +118,13 @@ public class FxApplication extends Application {
|
||||
});
|
||||
}
|
||||
|
||||
public void startLockWorkflow(Vault vault, Optional<Stage> owner) {
|
||||
Platform.runLater(() -> {
|
||||
lockWindowBuilderProvider.get().vault(vault).owner(owner).build().startLockWorkflow();
|
||||
LOG.debug("Start lock workflow for {}", vault.getDisplayName());
|
||||
});
|
||||
}
|
||||
|
||||
public void showQuitWindow(QuitResponse response) {
|
||||
Platform.runLater(() -> {
|
||||
quitWindow.get().showQuitWindow(response);
|
||||
|
||||
@@ -5,11 +5,8 @@
|
||||
*******************************************************************************/
|
||||
package org.cryptomator.ui.fxapp;
|
||||
|
||||
import dagger.BindsInstance;
|
||||
import dagger.Subcomponent;
|
||||
|
||||
import javax.inject.Named;
|
||||
|
||||
@FxApplicationScoped
|
||||
@Subcomponent(modules = FxApplicationModule.class)
|
||||
public interface FxApplicationComponent {
|
||||
@@ -19,9 +16,6 @@ public interface FxApplicationComponent {
|
||||
@Subcomponent.Builder
|
||||
interface Builder {
|
||||
|
||||
@BindsInstance
|
||||
Builder trayMenuSupported(@Named("trayMenuSupported") boolean trayMenuSupported);
|
||||
|
||||
FxApplicationComponent build();
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import dagger.Provides;
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
import org.cryptomator.ui.common.ErrorComponent;
|
||||
import org.cryptomator.ui.common.StageFactory;
|
||||
import org.cryptomator.ui.lock.LockComponent;
|
||||
import org.cryptomator.ui.mainwindow.MainWindowComponent;
|
||||
import org.cryptomator.ui.preferences.PreferencesComponent;
|
||||
import org.cryptomator.ui.quit.QuitComponent;
|
||||
@@ -27,7 +28,7 @@ import java.io.UncheckedIOException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@Module(includes = {UpdateCheckerModule.class}, subcomponents = {MainWindowComponent.class, PreferencesComponent.class, UnlockComponent.class, QuitComponent.class, ErrorComponent.class})
|
||||
@Module(includes = {UpdateCheckerModule.class}, subcomponents = {MainWindowComponent.class, PreferencesComponent.class, UnlockComponent.class, LockComponent.class, QuitComponent.class, ErrorComponent.class})
|
||||
abstract class FxApplicationModule {
|
||||
|
||||
@Provides
|
||||
|
||||
@@ -34,15 +34,15 @@ class AppLaunchEventHandler {
|
||||
this.vaultListManager = vaultListManager;
|
||||
}
|
||||
|
||||
public void startHandlingLaunchEvents(boolean hasTrayIcon) {
|
||||
executorService.submit(() -> handleLaunchEvents(hasTrayIcon));
|
||||
public void startHandlingLaunchEvents() {
|
||||
executorService.submit(this::handleLaunchEvents);
|
||||
}
|
||||
|
||||
private void handleLaunchEvents(boolean hasTrayIcon) {
|
||||
private void handleLaunchEvents() {
|
||||
try {
|
||||
while (!Thread.interrupted()) {
|
||||
AppLaunchEvent event = launchEventQueue.take();
|
||||
handleLaunchEvent(hasTrayIcon, event);
|
||||
handleLaunchEvent(event);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
LOG.warn("Interrupted launch event handler.");
|
||||
@@ -50,10 +50,10 @@ class AppLaunchEventHandler {
|
||||
}
|
||||
}
|
||||
|
||||
private void handleLaunchEvent(boolean hasTrayIcon, AppLaunchEvent event) {
|
||||
private void handleLaunchEvent(AppLaunchEvent event) {
|
||||
switch (event.getType()) {
|
||||
case REVEAL_APP -> fxApplicationStarter.get(hasTrayIcon).thenAccept(FxApplication::showMainWindow);
|
||||
case OPEN_FILE -> fxApplicationStarter.get(hasTrayIcon).thenRun(() -> {
|
||||
case REVEAL_APP -> fxApplicationStarter.get().thenAccept(FxApplication::showMainWindow);
|
||||
case OPEN_FILE -> fxApplicationStarter.get().thenRun(() -> {
|
||||
Platform.runLater(() -> {
|
||||
event.getPathsToOpen().forEach(this::addVault);
|
||||
});
|
||||
|
||||
@@ -83,7 +83,7 @@ public class AppLifecycleListener {
|
||||
if (allowQuitWithoutPrompt.get()) {
|
||||
decoratedQuitResponse.performQuit();
|
||||
} else {
|
||||
fxApplicationStarter.get(true).thenAccept(app -> app.showQuitWindow(decoratedQuitResponse));
|
||||
fxApplicationStarter.get().thenAccept(app -> app.showQuitWindow(decoratedQuitResponse));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,11 +113,11 @@ public class AppLifecycleListener {
|
||||
}
|
||||
|
||||
private void showPreferencesWindow(@SuppressWarnings("unused") EventObject actionEvent) {
|
||||
fxApplicationStarter.get(true).thenAccept(app -> app.showPreferencesWindow(SelectedPreferencesTab.ANY));
|
||||
fxApplicationStarter.get().thenAccept(app -> app.showPreferencesWindow(SelectedPreferencesTab.ANY));
|
||||
}
|
||||
|
||||
private void showAboutWindow(@SuppressWarnings("unused") AboutEvent aboutEvent) {
|
||||
fxApplicationStarter.get(true).thenAccept(app -> app.showPreferencesWindow(SelectedPreferencesTab.ABOUT));
|
||||
fxApplicationStarter.get().thenAccept(app -> app.showPreferencesWindow(SelectedPreferencesTab.ABOUT));
|
||||
}
|
||||
|
||||
private void forceUnmountRemainingVaults() {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.cryptomator.ui.launcher;
|
||||
|
||||
import dagger.Lazy;
|
||||
import org.cryptomator.ui.fxapp.FxApplication;
|
||||
import org.cryptomator.ui.fxapp.FxApplicationComponent;
|
||||
import org.slf4j.Logger;
|
||||
@@ -18,37 +19,36 @@ public class FxApplicationStarter {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(FxApplicationStarter.class);
|
||||
|
||||
private final FxApplicationComponent.Builder fxAppComponent;
|
||||
private final Lazy<FxApplicationComponent> fxAppComponent;
|
||||
private final ExecutorService executor;
|
||||
private final AtomicBoolean started;
|
||||
private final CompletableFuture<FxApplication> future;
|
||||
|
||||
@Inject
|
||||
public FxApplicationStarter(FxApplicationComponent.Builder fxAppComponent, ExecutorService executor) {
|
||||
public FxApplicationStarter(Lazy<FxApplicationComponent> fxAppComponent, ExecutorService executor) {
|
||||
this.fxAppComponent = fxAppComponent;
|
||||
this.executor = executor;
|
||||
this.started = new AtomicBoolean();
|
||||
this.future = new CompletableFuture<>();
|
||||
}
|
||||
|
||||
public CompletionStage<FxApplication> get(boolean hasTrayIcon) {
|
||||
public CompletionStage<FxApplication> get() {
|
||||
if (!started.getAndSet(true)) {
|
||||
start(hasTrayIcon);
|
||||
start();
|
||||
}
|
||||
return future;
|
||||
}
|
||||
|
||||
private void start(boolean hasTrayIcon) {
|
||||
private void start() {
|
||||
executor.submit(() -> {
|
||||
LOG.debug("Starting JavaFX runtime...");
|
||||
Platform.startup(() -> {
|
||||
assert Platform.isFxApplicationThread();
|
||||
LOG.info("JavaFX Runtime started.");
|
||||
FxApplication app = fxAppComponent.trayMenuSupported(hasTrayIcon).build().application();
|
||||
FxApplication app = fxAppComponent.get().application();
|
||||
app.start();
|
||||
future.complete(app);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.cryptomator.ui.launcher;
|
||||
|
||||
import dagger.Lazy;
|
||||
import org.cryptomator.common.settings.Settings;
|
||||
import org.cryptomator.common.vaults.Vault;
|
||||
import org.cryptomator.integrations.tray.TrayIntegrationProvider;
|
||||
@@ -24,60 +25,66 @@ public class UiLauncher {
|
||||
|
||||
private final Settings settings;
|
||||
private final ObservableList<Vault> vaults;
|
||||
private final TrayMenuComponent.Builder trayComponent;
|
||||
private final Lazy<TrayMenuComponent> trayMenu;
|
||||
private final FxApplicationStarter fxApplicationStarter;
|
||||
private final AppLaunchEventHandler launchEventHandler;
|
||||
private final Optional<TrayIntegrationProvider> trayIntegration;
|
||||
|
||||
@Inject
|
||||
public UiLauncher(Settings settings, ObservableList<Vault> vaults, TrayMenuComponent.Builder trayComponent, FxApplicationStarter fxApplicationStarter, AppLaunchEventHandler launchEventHandler, Optional<TrayIntegrationProvider> trayIntegration) {
|
||||
public UiLauncher(Settings settings, ObservableList<Vault> vaults, Lazy<TrayMenuComponent> trayMenu, FxApplicationStarter fxApplicationStarter, AppLaunchEventHandler launchEventHandler, Optional<TrayIntegrationProvider> trayIntegration) {
|
||||
this.settings = settings;
|
||||
this.vaults = vaults;
|
||||
this.trayComponent = trayComponent;
|
||||
this.trayMenu = trayMenu;
|
||||
this.fxApplicationStarter = fxApplicationStarter;
|
||||
this.launchEventHandler = launchEventHandler;
|
||||
this.trayIntegration = trayIntegration;
|
||||
}
|
||||
|
||||
public void launch() {
|
||||
final boolean hasTrayIcon;
|
||||
if (SystemTray.isSupported()) {
|
||||
trayComponent.build().addIconToSystemTray();
|
||||
hasTrayIcon = true;
|
||||
boolean hidden = settings.startHidden().get();
|
||||
if (SystemTray.isSupported() && settings.showTrayIcon().get()) {
|
||||
trayMenu.get().initializeTrayIcon();
|
||||
launch(true, hidden);
|
||||
} else {
|
||||
hasTrayIcon = false;
|
||||
launch(false, hidden);
|
||||
}
|
||||
}
|
||||
|
||||
// show window on start?
|
||||
if (hasTrayIcon && settings.startHidden().get()) {
|
||||
private void launch(boolean withTrayIcon, boolean hidden) {
|
||||
// start hidden, minimized or normal?
|
||||
if (withTrayIcon && hidden) {
|
||||
LOG.debug("Hiding application...");
|
||||
trayIntegration.ifPresent(TrayIntegrationProvider::minimizedToTray);
|
||||
} else if (!withTrayIcon && hidden) {
|
||||
LOG.debug("Minimizing application...");
|
||||
showMainWindowAsync(true);
|
||||
} else {
|
||||
showMainWindowAsync(hasTrayIcon);
|
||||
LOG.debug("Showing application...");
|
||||
showMainWindowAsync(false);
|
||||
}
|
||||
|
||||
// register app reopen listener
|
||||
Desktop.getDesktop().addAppEventListener((AppReopenedListener) e -> showMainWindowAsync(hasTrayIcon));
|
||||
Desktop.getDesktop().addAppEventListener((AppReopenedListener) e -> showMainWindowAsync(false));
|
||||
|
||||
// auto unlock
|
||||
Collection<Vault> vaultsToAutoUnlock = vaults.filtered(this::shouldAttemptAutoUnlock);
|
||||
if (!vaultsToAutoUnlock.isEmpty()) {
|
||||
fxApplicationStarter.get(hasTrayIcon).thenAccept(app -> {
|
||||
fxApplicationStarter.get().thenAccept(app -> {
|
||||
for (Vault vault : vaultsToAutoUnlock) {
|
||||
app.startUnlockWorkflow(vault, Optional.empty());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
launchEventHandler.startHandlingLaunchEvents(hasTrayIcon);
|
||||
launchEventHandler.startHandlingLaunchEvents();
|
||||
}
|
||||
|
||||
private boolean shouldAttemptAutoUnlock(Vault vault) {
|
||||
return vault.isLocked() && vault.getVaultSettings().unlockAfterStartup().get();
|
||||
}
|
||||
|
||||
private void showMainWindowAsync(boolean hasTrayIcon) {
|
||||
fxApplicationStarter.get(hasTrayIcon).thenAccept(FxApplication::showMainWindow);
|
||||
private void showMainWindowAsync(boolean minimize) {
|
||||
fxApplicationStarter.get().thenCompose(FxApplication::showMainWindow).thenAccept(win -> win.setIconified(minimize));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -19,6 +19,18 @@ import java.util.concurrent.BlockingQueue;
|
||||
@Module(subcomponents = {TrayMenuComponent.class, FxApplicationComponent.class})
|
||||
public abstract class UiLauncherModule {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
static TrayMenuComponent provideTrayMenuComponent(TrayMenuComponent.Builder builder) {
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
static FxApplicationComponent provideFxApplicationComponent(FxApplicationComponent.Builder builder) {
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
static Optional<UiAppearanceProvider> provideAppearanceProvider() {
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
package org.cryptomator.ui.lock;
|
||||
|
||||
import dagger.BindsInstance;
|
||||
import dagger.Subcomponent;
|
||||
import org.cryptomator.common.vaults.Vault;
|
||||
|
||||
import javax.inject.Named;
|
||||
import javafx.stage.Stage;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
|
||||
@LockScoped
|
||||
@Subcomponent(modules = {LockModule.class})
|
||||
public interface LockComponent {
|
||||
|
||||
ExecutorService defaultExecutorService();
|
||||
|
||||
LockWorkflow lockWorkflow();
|
||||
|
||||
default Future<Void> startLockWorkflow() {
|
||||
LockWorkflow workflow = lockWorkflow();
|
||||
defaultExecutorService().submit(workflow);
|
||||
return workflow;
|
||||
}
|
||||
|
||||
@Subcomponent.Builder
|
||||
interface Builder {
|
||||
|
||||
@BindsInstance
|
||||
LockComponent.Builder vault(@LockWindow Vault vault);
|
||||
|
||||
@BindsInstance
|
||||
LockComponent.Builder owner(@Named("lockWindowOwner") Optional<Stage> owner);
|
||||
|
||||
LockComponent build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package org.cryptomator.ui.lock;
|
||||
|
||||
import org.cryptomator.common.vaults.Vault;
|
||||
import org.cryptomator.ui.common.FxController;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
@LockScoped
|
||||
public class LockFailedController implements FxController {
|
||||
|
||||
private final Stage window;
|
||||
private final Vault vault;
|
||||
|
||||
@Inject
|
||||
public LockFailedController(@LockWindow Stage window, @LockWindow Vault vault) {
|
||||
this.window = window;
|
||||
this.vault = vault;
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void close() {
|
||||
window.close();
|
||||
}
|
||||
|
||||
// ----- Getter & Setter -----
|
||||
public String getVaultName() {
|
||||
return vault.getDisplayName();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package org.cryptomator.ui.lock;
|
||||
|
||||
import org.cryptomator.common.vaults.Vault;
|
||||
import org.cryptomator.ui.common.FxController;
|
||||
import org.cryptomator.ui.common.UserInteractionLock;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.stage.Stage;
|
||||
import javafx.stage.WindowEvent;
|
||||
|
||||
@LockScoped
|
||||
public class LockForcedController implements FxController {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(LockForcedController.class);
|
||||
|
||||
private final Stage window;
|
||||
private final Vault vault;
|
||||
private final UserInteractionLock<LockModule.ForceLockDecision> forceLockDecisionLock;
|
||||
|
||||
@Inject
|
||||
public LockForcedController(@LockWindow Stage window, @LockWindow Vault vault, UserInteractionLock<LockModule.ForceLockDecision> forceLockDecisionLock) {
|
||||
this.window = window;
|
||||
this.vault = vault;
|
||||
this.forceLockDecisionLock = forceLockDecisionLock;
|
||||
this.window.setOnHiding(this::windowClosed);
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void cancel() {
|
||||
forceLockDecisionLock.interacted(LockModule.ForceLockDecision.CANCEL);
|
||||
window.close();
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void confirmForcedLock() {
|
||||
forceLockDecisionLock.interacted(LockModule.ForceLockDecision.FORCE);
|
||||
window.close();
|
||||
}
|
||||
|
||||
private void windowClosed(WindowEvent windowEvent) {
|
||||
// if not already interacted, set the decision to CANCEL
|
||||
if (forceLockDecisionLock.awaitingInteraction().get()) {
|
||||
LOG.debug("Lock canceled in force-lock-phase by user.");
|
||||
forceLockDecisionLock.interacted(LockModule.ForceLockDecision.CANCEL);
|
||||
}
|
||||
}
|
||||
|
||||
// ----- Getter & Setter -----
|
||||
|
||||
public String getVaultName() {
|
||||
return vault.getDisplayName();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package org.cryptomator.ui.lock;
|
||||
|
||||
import dagger.Binds;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import dagger.multibindings.IntoMap;
|
||||
import org.cryptomator.common.vaults.Vault;
|
||||
import org.cryptomator.ui.common.DefaultSceneFactory;
|
||||
import org.cryptomator.ui.common.FXMLLoaderFactory;
|
||||
import org.cryptomator.ui.common.FxController;
|
||||
import org.cryptomator.ui.common.FxControllerKey;
|
||||
import org.cryptomator.ui.common.FxmlFile;
|
||||
import org.cryptomator.ui.common.FxmlScene;
|
||||
import org.cryptomator.ui.common.StageFactory;
|
||||
import org.cryptomator.ui.common.UserInteractionLock;
|
||||
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Provider;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.stage.Modality;
|
||||
import javafx.stage.Stage;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
@Module
|
||||
abstract class LockModule {
|
||||
|
||||
enum ForceLockDecision {
|
||||
CANCEL,
|
||||
FORCE;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@LockScoped
|
||||
static UserInteractionLock<LockModule.ForceLockDecision> provideForceLockDecisionLock() {
|
||||
return new UserInteractionLock<>(null);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@LockWindow
|
||||
@LockScoped
|
||||
static FXMLLoaderFactory provideFxmlLoaderFactory(Map<Class<? extends FxController>, Provider<FxController>> factories, DefaultSceneFactory sceneFactory, ResourceBundle resourceBundle) {
|
||||
return new FXMLLoaderFactory(factories, sceneFactory, resourceBundle);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@LockWindow
|
||||
@LockScoped
|
||||
static Stage provideWindow(StageFactory factory, @LockWindow Vault vault, @Named("lockWindowOwner") Optional<Stage> owner) {
|
||||
Stage stage = factory.create();
|
||||
stage.setTitle(vault.getDisplayName());
|
||||
stage.setResizable(false);
|
||||
if (owner.isPresent()) {
|
||||
stage.initOwner(owner.get());
|
||||
stage.initModality(Modality.WINDOW_MODAL);
|
||||
} else {
|
||||
stage.initModality(Modality.APPLICATION_MODAL);
|
||||
}
|
||||
return stage;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@FxmlScene(FxmlFile.LOCK_FORCED)
|
||||
@LockScoped
|
||||
static Scene provideForceLockScene(@LockWindow FXMLLoaderFactory fxmlLoaders) {
|
||||
return fxmlLoaders.createScene("/fxml/lock_forced.fxml");
|
||||
}
|
||||
|
||||
@Provides
|
||||
@FxmlScene(FxmlFile.LOCK_FAILED)
|
||||
@LockScoped
|
||||
static Scene provideLockFailedScene(@LockWindow FXMLLoaderFactory fxmlLoaders) {
|
||||
return fxmlLoaders.createScene("/fxml/lock_failed.fxml");
|
||||
}
|
||||
|
||||
// ------------------
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@FxControllerKey(LockForcedController.class)
|
||||
abstract FxController bindLockForcedController(LockForcedController controller);
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@FxControllerKey(LockFailedController.class)
|
||||
abstract FxController bindLockFailedController(LockFailedController controller);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package org.cryptomator.ui.lock;
|
||||
|
||||
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 LockScoped {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package org.cryptomator.ui.lock;
|
||||
|
||||
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 LockWindow {
|
||||
|
||||
}
|
||||
105
main/ui/src/main/java/org/cryptomator/ui/lock/LockWorkflow.java
Normal file
105
main/ui/src/main/java/org/cryptomator/ui/lock/LockWorkflow.java
Normal file
@@ -0,0 +1,105 @@
|
||||
package org.cryptomator.ui.lock;
|
||||
|
||||
import dagger.Lazy;
|
||||
import org.cryptomator.common.vaults.Vault;
|
||||
import org.cryptomator.common.vaults.VaultState;
|
||||
import org.cryptomator.common.vaults.Volume;
|
||||
import org.cryptomator.ui.common.FxmlFile;
|
||||
import org.cryptomator.ui.common.FxmlScene;
|
||||
import org.cryptomator.ui.common.UserInteractionLock;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javafx.application.Platform;
|
||||
import javafx.concurrent.Task;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.stage.Stage;
|
||||
import javafx.stage.Window;
|
||||
|
||||
/**
|
||||
* The sequence of actions performed and checked during lock of a vault.
|
||||
* <p>
|
||||
* This class implements the Task interface, sucht that it can run in the background with some possible forground operations/requests to the ui, without blocking the main app.
|
||||
* If the task state is
|
||||
* <li>succeeded, the vault was successfully locked;</li>
|
||||
* <li>canceled, the lock was canceled;</li>
|
||||
* <li>failed, the lock failed due to an exception.</li>
|
||||
*/
|
||||
public class LockWorkflow extends Task<Void> {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(LockWorkflow.class);
|
||||
|
||||
private final Stage lockWindow;
|
||||
private final Vault vault;
|
||||
private final UserInteractionLock<LockModule.ForceLockDecision> forceLockDecisionLock;
|
||||
private final Lazy<Scene> lockForcedScene;
|
||||
private final Lazy<Scene> lockFailedScene;
|
||||
|
||||
@Inject
|
||||
public LockWorkflow(@LockWindow Stage lockWindow, @LockWindow Vault vault, UserInteractionLock<LockModule.ForceLockDecision> forceLockDecisionLock, @FxmlScene(FxmlFile.LOCK_FORCED) Lazy<Scene> lockForcedScene, @FxmlScene(FxmlFile.LOCK_FAILED) Lazy<Scene> lockFailedScene) {
|
||||
this.lockWindow = lockWindow;
|
||||
this.vault = vault;
|
||||
this.forceLockDecisionLock = forceLockDecisionLock;
|
||||
this.lockForcedScene = lockForcedScene;
|
||||
this.lockFailedScene = lockFailedScene;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void call() throws Volume.VolumeException, InterruptedException {
|
||||
try {
|
||||
vault.lock(false);
|
||||
} catch (Volume.VolumeException e) {
|
||||
LOG.debug("Regular lock of {} failed.", vault.getDisplayName(), e);
|
||||
var decision = askUserForAction();
|
||||
switch (decision) {
|
||||
case FORCE -> vault.lock(true);
|
||||
case CANCEL -> cancel(false);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private LockModule.ForceLockDecision askUserForAction() throws InterruptedException {
|
||||
// show forcedLock dialogue ...
|
||||
Platform.runLater(() -> {
|
||||
lockWindow.setScene(lockForcedScene.get());
|
||||
lockWindow.show();
|
||||
Window owner = lockWindow.getOwner();
|
||||
if (owner != null) {
|
||||
lockWindow.setX(owner.getX() + (owner.getWidth() - lockWindow.getWidth()) / 2);
|
||||
lockWindow.setY(owner.getY() + (owner.getHeight() - lockWindow.getHeight()) / 2);
|
||||
} else {
|
||||
lockWindow.centerOnScreen();
|
||||
}
|
||||
});
|
||||
// ... and wait for answer
|
||||
return forceLockDecisionLock.awaitInteraction();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void scheduled() {
|
||||
vault.setState(VaultState.PROCESSING);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void succeeded() {
|
||||
LOG.info("Lock of {} succeeded.", vault.getDisplayName());
|
||||
vault.setState(VaultState.LOCKED);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void failed() {
|
||||
LOG.warn("Failed to lock {}.", vault.getDisplayName());
|
||||
vault.setState(VaultState.UNLOCKED);
|
||||
lockWindow.setScene(lockFailedScene.get());
|
||||
lockWindow.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void cancelled() {
|
||||
LOG.debug("Lock of {} canceled.", vault.getDisplayName());
|
||||
vault.setState(VaultState.UNLOCKED);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -26,7 +26,6 @@ public interface MainWindowComponent {
|
||||
default Stage showMainWindow() {
|
||||
Stage stage = window();
|
||||
stage.setScene(scene().get());
|
||||
stage.setIconified(false);
|
||||
stage.show();
|
||||
stage.toFront();
|
||||
stage.requestFocus();
|
||||
|
||||
@@ -7,13 +7,14 @@ import org.cryptomator.ui.fxapp.FxApplication;
|
||||
import org.cryptomator.ui.fxapp.UpdateChecker;
|
||||
import org.cryptomator.ui.launcher.AppLifecycleListener;
|
||||
import org.cryptomator.ui.preferences.SelectedPreferencesTab;
|
||||
import org.cryptomator.ui.traymenu.TrayMenuComponent;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javafx.beans.binding.Bindings;
|
||||
import javafx.beans.binding.BooleanBinding;
|
||||
import javafx.beans.property.ReadOnlyBooleanProperty;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.stage.Stage;
|
||||
@@ -23,32 +24,31 @@ public class MainWindowTitleController implements FxController {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(MainWindowTitleController.class);
|
||||
|
||||
public HBox titleBar;
|
||||
|
||||
private final AppLifecycleListener appLifecycle;
|
||||
private final Stage window;
|
||||
private final FxApplication application;
|
||||
private final boolean minimizeToSysTray;
|
||||
private final boolean trayMenuInitialized;
|
||||
private final UpdateChecker updateChecker;
|
||||
private final BooleanBinding updateAvailable;
|
||||
private final LicenseHolder licenseHolder;
|
||||
private final Settings settings;
|
||||
private final BooleanBinding debugModeEnabled;
|
||||
private final BooleanBinding showMinimizeButton;
|
||||
|
||||
public HBox titleBar;
|
||||
private double xOffset;
|
||||
private double yOffset;
|
||||
|
||||
@Inject
|
||||
MainWindowTitleController(AppLifecycleListener appLifecycle, @MainWindow Stage window, FxApplication application, @Named("trayMenuSupported") boolean minimizeToSysTray, UpdateChecker updateChecker, LicenseHolder licenseHolder, Settings settings) {
|
||||
MainWindowTitleController(AppLifecycleListener appLifecycle, @MainWindow Stage window, FxApplication application, TrayMenuComponent trayMenu, UpdateChecker updateChecker, LicenseHolder licenseHolder, Settings settings) {
|
||||
this.appLifecycle = appLifecycle;
|
||||
this.window = window;
|
||||
this.application = application;
|
||||
this.minimizeToSysTray = minimizeToSysTray;
|
||||
this.trayMenuInitialized = trayMenu.isInitialized();
|
||||
this.updateChecker = updateChecker;
|
||||
this.updateAvailable = updateChecker.latestVersionProperty().isNotNull();
|
||||
this.licenseHolder = licenseHolder;
|
||||
this.settings = settings;
|
||||
this.debugModeEnabled = Bindings.createBooleanBinding(this::isDebugModeEnabled, settings.debugMode());
|
||||
this.showMinimizeButton = Bindings.createBooleanBinding(this::isShowMinimizeButton, settings.showMinimizeButton(), settings.showTrayIcon());
|
||||
}
|
||||
|
||||
@FXML
|
||||
@@ -71,7 +71,7 @@ public class MainWindowTitleController implements FxController {
|
||||
|
||||
@FXML
|
||||
public void close() {
|
||||
if (minimizeToSysTray) {
|
||||
if (trayMenuInitialized) {
|
||||
window.close();
|
||||
} else {
|
||||
appLifecycle.quit();
|
||||
@@ -112,15 +112,24 @@ public class MainWindowTitleController implements FxController {
|
||||
return updateAvailable.get();
|
||||
}
|
||||
|
||||
public boolean isMinimizeToSysTray() {
|
||||
return minimizeToSysTray;
|
||||
public boolean isTrayIconPresent() {
|
||||
return trayMenuInitialized;
|
||||
}
|
||||
|
||||
public BooleanBinding debugModeEnabledProperty() {
|
||||
return debugModeEnabled;
|
||||
public ReadOnlyBooleanProperty debugModeEnabledProperty() {
|
||||
return settings.debugMode();
|
||||
}
|
||||
|
||||
public boolean isDebugModeEnabled() {
|
||||
return settings.debugMode().get();
|
||||
return debugModeEnabledProperty().get();
|
||||
}
|
||||
|
||||
public BooleanBinding showMinimizeButtonProperty() {
|
||||
return showMinimizeButton;
|
||||
}
|
||||
|
||||
public boolean isShowMinimizeButton() {
|
||||
// always show the minimize button if no tray icon is present OR it is explicitily enabled
|
||||
return !trayMenuInitialized || settings.showMinimizeButton().get();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,25 +6,32 @@ import com.google.common.cache.LoadingCache;
|
||||
import org.cryptomator.common.vaults.Vault;
|
||||
import org.cryptomator.ui.common.FxController;
|
||||
import org.cryptomator.ui.common.VaultService;
|
||||
import org.cryptomator.ui.fxapp.FxApplication;
|
||||
import org.cryptomator.ui.stats.VaultStatisticsComponent;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javafx.beans.property.ObjectProperty;
|
||||
import javafx.beans.property.ReadOnlyObjectProperty;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.stage.Stage;
|
||||
import java.util.Optional;
|
||||
|
||||
@MainWindowScoped
|
||||
public class VaultDetailUnlockedController implements FxController {
|
||||
|
||||
private final ReadOnlyObjectProperty<Vault> vault;
|
||||
private final FxApplication application;
|
||||
private final VaultService vaultService;
|
||||
private final Stage mainWindow;
|
||||
private final LoadingCache<Vault, VaultStatisticsComponent> vaultStats;
|
||||
private final VaultStatisticsComponent.Builder vaultStatsBuilder;
|
||||
|
||||
@Inject
|
||||
public VaultDetailUnlockedController(ObjectProperty<Vault> vault, VaultService vaultService, VaultStatisticsComponent.Builder vaultStatsBuilder) {
|
||||
public VaultDetailUnlockedController(ObjectProperty<Vault> vault, FxApplication application, VaultService vaultService, VaultStatisticsComponent.Builder vaultStatsBuilder, @MainWindow Stage mainWindow) {
|
||||
this.vault = vault;
|
||||
this.application = application;
|
||||
this.vaultService = vaultService;
|
||||
this.mainWindow = mainWindow;
|
||||
this.vaultStats = CacheBuilder.newBuilder().weakValues().build(CacheLoader.from(this::buildVaultStats));
|
||||
this.vaultStatsBuilder = vaultStatsBuilder;
|
||||
}
|
||||
@@ -40,8 +47,7 @@ public class VaultDetailUnlockedController implements FxController {
|
||||
|
||||
@FXML
|
||||
public void lock() {
|
||||
vaultService.lock(vault.get(), false);
|
||||
// TODO count lock attempts, and allow forced lock
|
||||
application.startLockWorkflow(vault.get(), Optional.of(mainWindow));
|
||||
}
|
||||
|
||||
@FXML
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
package org.cryptomator.ui.preferences;
|
||||
|
||||
import org.cryptomator.integrations.autostart.AutoStartProvider;
|
||||
import org.cryptomator.integrations.autostart.ToggleAutoStartFailedException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.CompletionStage;
|
||||
|
||||
@Deprecated
|
||||
class AutoStartMacStrategy implements AutoStartStrategy {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(AutoStartMacStrategy.class);
|
||||
|
||||
private final AutoStartProvider autoStartProvider;
|
||||
|
||||
public AutoStartMacStrategy(AutoStartProvider autoStartProvider) {
|
||||
this.autoStartProvider = autoStartProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletionStage<Boolean> isAutoStartEnabled() {
|
||||
return CompletableFuture.completedFuture(autoStartProvider.isEnabled());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enableAutoStart() throws TogglingAutoStartFailedException {
|
||||
try {
|
||||
autoStartProvider.enable();
|
||||
LOG.debug("Added login item.");
|
||||
} catch (ToggleAutoStartFailedException e) {
|
||||
throw new TogglingAutoStartFailedException("Failed to add login item.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disableAutoStart() throws TogglingAutoStartFailedException {
|
||||
try {
|
||||
autoStartProvider.disable();
|
||||
LOG.debug("Removed login item.");
|
||||
} catch (ToggleAutoStartFailedException e) {
|
||||
throw new TogglingAutoStartFailedException("Failed to remove login item.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
package org.cryptomator.ui.preferences;
|
||||
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
import org.cryptomator.integrations.autostart.AutoStartProvider;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@Deprecated
|
||||
@Module
|
||||
abstract class AutoStartModule {
|
||||
|
||||
@Provides
|
||||
@PreferencesScoped
|
||||
public static Optional<AutoStartStrategy> provideAutoStartStrategy(Optional<AutoStartProvider> autoStartProvider) {
|
||||
if (SystemUtils.IS_OS_MAC_OSX && autoStartProvider.isPresent()) {
|
||||
return Optional.of(new AutoStartMacStrategy(autoStartProvider.get()));
|
||||
} else if (SystemUtils.IS_OS_WINDOWS) {
|
||||
Optional<String> exeName = ProcessHandle.current().info().command();
|
||||
return exeName.map(AutoStartWinStrategy::new);
|
||||
} else {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package org.cryptomator.ui.preferences;
|
||||
|
||||
import java.util.concurrent.CompletionStage;
|
||||
|
||||
@Deprecated
|
||||
public interface AutoStartStrategy {
|
||||
|
||||
CompletionStage<Boolean> isAutoStartEnabled();
|
||||
|
||||
void enableAutoStart() throws TogglingAutoStartFailedException;
|
||||
|
||||
void disableAutoStart() throws TogglingAutoStartFailedException;
|
||||
|
||||
class TogglingAutoStartFailedException extends Exception {
|
||||
|
||||
public TogglingAutoStartFailedException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public TogglingAutoStartFailedException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,209 +0,0 @@
|
||||
package org.cryptomator.ui.preferences;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.NoSuchFileException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.CompletionStage;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* OS specific class to check, en- and disable the auto start on Windows.
|
||||
* <p>
|
||||
* Two strategies are implemented for this feature, the first uses the registry and the second one the autostart folder.
|
||||
* <p>
|
||||
* The registry strategy checks/add/removes at the registry key {@value HKCU_AUTOSTART_KEY} an entry for Cryptomator.
|
||||
* The folder strategy checks/add/removes at the location {@value WINDOWS_START_MENU_ENTRY}.
|
||||
* <p>
|
||||
* To check if the feature is active, both strategies are applied.
|
||||
* To enable the feature, first the registry is tried and only on failure the autostart folder is used.
|
||||
* To disable it, first it is determined by an internal state, which strategies must be used and in the second step those are executed.
|
||||
*
|
||||
* @apiNote This class is not thread safe, hence it should be avoided to call its methods simultaniously by different threads.
|
||||
* @deprecated To be moved to integration-win project
|
||||
*/
|
||||
@Deprecated
|
||||
class AutoStartWinStrategy implements AutoStartStrategy {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(AutoStartWinStrategy.class);
|
||||
private static final String HKCU_AUTOSTART_KEY = "\"HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run\"";
|
||||
private static final String AUTOSTART_VALUE = "Cryptomator";
|
||||
private static final String WINDOWS_START_MENU_ENTRY = "\\AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Cryptomator.lnk";
|
||||
|
||||
private final String exePath;
|
||||
|
||||
private boolean activatedUsingFolder;
|
||||
private boolean activatedUsingRegistry;
|
||||
|
||||
public AutoStartWinStrategy(String exePath) {
|
||||
this.exePath = exePath;
|
||||
this.activatedUsingFolder = false;
|
||||
this.activatedUsingRegistry = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletionStage<Boolean> isAutoStartEnabled() {
|
||||
return isAutoStartEnabledUsingRegistry().thenCombine(isAutoStartEnabledUsingFolder(), (bReg, bFolder) -> bReg || bFolder);
|
||||
}
|
||||
|
||||
private CompletableFuture<Boolean> isAutoStartEnabledUsingFolder() {
|
||||
Path autoStartEntry = Path.of(System.getProperty("user.home") + WINDOWS_START_MENU_ENTRY);
|
||||
this.activatedUsingFolder = Files.exists(autoStartEntry);
|
||||
return CompletableFuture.completedFuture(activatedUsingFolder);
|
||||
}
|
||||
|
||||
private CompletableFuture<Boolean> isAutoStartEnabledUsingRegistry() {
|
||||
ProcessBuilder regQuery = new ProcessBuilder("reg", "query", HKCU_AUTOSTART_KEY, //
|
||||
"/v", AUTOSTART_VALUE);
|
||||
try {
|
||||
Process proc = regQuery.start();
|
||||
return proc.onExit().thenApply(p -> {
|
||||
this.activatedUsingRegistry = p.exitValue() == 0;
|
||||
return activatedUsingRegistry;
|
||||
});
|
||||
} catch (IOException e) {
|
||||
LOG.debug("Failed to query {} from registry key {}", AUTOSTART_VALUE, HKCU_AUTOSTART_KEY);
|
||||
return CompletableFuture.completedFuture(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enableAutoStart() throws TogglingAutoStartFailedException {
|
||||
try {
|
||||
enableAutoStartUsingRegistry().thenAccept((Void v) -> this.activatedUsingRegistry = true).exceptionallyCompose(e -> {
|
||||
LOG.debug("Falling back to using autostart folder.");
|
||||
return this.enableAutoStartUsingFolder();
|
||||
}).thenAccept((Void v) -> this.activatedUsingFolder = true).get();
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
throw new TogglingAutoStartFailedException("Execution of enabling auto start setting was interrupted.");
|
||||
} catch (ExecutionException e) {
|
||||
throw new TogglingAutoStartFailedException("Enabling auto start failed both using registry and auto start folder.");
|
||||
}
|
||||
}
|
||||
|
||||
private CompletableFuture<Void> enableAutoStartUsingRegistry() {
|
||||
ProcessBuilder regAdd = new ProcessBuilder("reg", "add", HKCU_AUTOSTART_KEY, //
|
||||
"/v", AUTOSTART_VALUE, //
|
||||
"/t", "REG_SZ", //
|
||||
"/d", "\"" + exePath + "\"", //
|
||||
"/f");
|
||||
try {
|
||||
Process proc = regAdd.start();
|
||||
boolean finishedInTime = waitForProcessOrCancel(proc, 5, TimeUnit.SECONDS);
|
||||
if (finishedInTime && proc.exitValue() == 0) {
|
||||
LOG.debug("Added {} to registry key {}.", AUTOSTART_VALUE, HKCU_AUTOSTART_KEY);
|
||||
return CompletableFuture.completedFuture(null);
|
||||
} else {
|
||||
throw new IOException("Process exited with error code " + proc.exitValue());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
LOG.debug("Registry could not be edited to set auto start.", e);
|
||||
return CompletableFuture.failedFuture(new SystemCommandException("Adding registry value failed."));
|
||||
}
|
||||
}
|
||||
|
||||
private CompletableFuture<Void> enableAutoStartUsingFolder() {
|
||||
String autoStartFolderEntry = System.getProperty("user.home") + WINDOWS_START_MENU_ENTRY;
|
||||
String createShortcutCommand = "$s=(New-Object -COM WScript.Shell).CreateShortcut('" + autoStartFolderEntry + "');$s.TargetPath='" + exePath + "';$s.Save();";
|
||||
ProcessBuilder shortcutAdd = new ProcessBuilder("cmd", "/c", "Start powershell " + createShortcutCommand);
|
||||
try {
|
||||
Process proc = shortcutAdd.start();
|
||||
boolean finishedInTime = waitForProcessOrCancel(proc, 5, TimeUnit.SECONDS);
|
||||
if (finishedInTime && proc.exitValue() == 0) {
|
||||
LOG.debug("Created file {} for auto start.", autoStartFolderEntry);
|
||||
return CompletableFuture.completedFuture(null);
|
||||
} else {
|
||||
throw new IOException("Process exited with error code " + proc.exitValue());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
LOG.debug("Adding entry to auto start folder failed.", e);
|
||||
return CompletableFuture.failedFuture(new SystemCommandException("Adding entry to auto start folder failed."));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void disableAutoStart() throws TogglingAutoStartFailedException {
|
||||
if (activatedUsingRegistry) {
|
||||
disableAutoStartUsingRegistry().whenComplete((voit, ex) -> {
|
||||
if (ex == null) {
|
||||
this.activatedUsingRegistry = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (activatedUsingFolder) {
|
||||
disableAutoStartUsingFolder().whenComplete((voit, ex) -> {
|
||||
if (ex == null) {
|
||||
this.activatedUsingFolder = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (activatedUsingRegistry || activatedUsingFolder) {
|
||||
throw new TogglingAutoStartFailedException("Disabling auto start failed using registry and/or auto start folder.");
|
||||
}
|
||||
}
|
||||
|
||||
public CompletableFuture<Void> disableAutoStartUsingRegistry() {
|
||||
ProcessBuilder regRemove = new ProcessBuilder("reg", "delete", HKCU_AUTOSTART_KEY, //
|
||||
"/v", AUTOSTART_VALUE, //
|
||||
"/f");
|
||||
try {
|
||||
Process proc = regRemove.start();
|
||||
boolean finishedInTime = waitForProcessOrCancel(proc, 5, TimeUnit.SECONDS);
|
||||
if (finishedInTime && proc.exitValue() == 0) {
|
||||
LOG.debug("Removed {} from registry key {}.", AUTOSTART_VALUE, HKCU_AUTOSTART_KEY);
|
||||
return CompletableFuture.completedFuture(null);
|
||||
} else {
|
||||
throw new IOException("Process exited with error code " + proc.exitValue());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
LOG.debug("Registry could not be edited to remove auto start.", e);
|
||||
return CompletableFuture.failedFuture(new SystemCommandException("Removing registry value failed."));
|
||||
}
|
||||
}
|
||||
|
||||
private CompletableFuture<Void> disableAutoStartUsingFolder() {
|
||||
try {
|
||||
Files.delete(Path.of(WINDOWS_START_MENU_ENTRY));
|
||||
LOG.debug("Successfully deleted {}.", WINDOWS_START_MENU_ENTRY);
|
||||
return CompletableFuture.completedFuture(null);
|
||||
} catch (NoSuchFileException e) {
|
||||
//that is also okay
|
||||
return CompletableFuture.completedFuture(null);
|
||||
} catch (IOException e) {
|
||||
LOG.debug("Failed to delete entry from auto start folder.", e);
|
||||
return CompletableFuture.failedFuture(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean waitForProcessOrCancel(Process proc, int timeout, TimeUnit timeUnit) {
|
||||
boolean finishedInTime = false;
|
||||
try {
|
||||
finishedInTime = proc.waitFor(timeout, timeUnit);
|
||||
} catch (InterruptedException e) {
|
||||
LOG.error("Timeout while reading registry", e);
|
||||
Thread.currentThread().interrupt();
|
||||
} finally {
|
||||
if (!finishedInTime) {
|
||||
proc.destroyForcibly();
|
||||
}
|
||||
}
|
||||
return finishedInTime;
|
||||
}
|
||||
|
||||
private class SystemCommandException extends RuntimeException {
|
||||
|
||||
public SystemCommandException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,19 +5,19 @@ import org.cryptomator.common.LicenseHolder;
|
||||
import org.cryptomator.common.settings.KeychainBackend;
|
||||
import org.cryptomator.common.settings.Settings;
|
||||
import org.cryptomator.common.settings.UiTheme;
|
||||
import org.cryptomator.integrations.autostart.AutoStartProvider;
|
||||
import org.cryptomator.integrations.autostart.ToggleAutoStartFailedException;
|
||||
import org.cryptomator.integrations.keychain.KeychainAccessProvider;
|
||||
import org.cryptomator.ui.common.ErrorComponent;
|
||||
import org.cryptomator.ui.common.FxController;
|
||||
import org.cryptomator.ui.traymenu.TrayMenuComponent;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javafx.application.Application;
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.property.ObjectProperty;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
import javafx.concurrent.Task;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.geometry.NodeOrientation;
|
||||
import javafx.scene.control.CheckBox;
|
||||
@@ -31,7 +31,6 @@ import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@PreferencesScoped
|
||||
@@ -41,11 +40,11 @@ public class GeneralPreferencesController implements FxController {
|
||||
|
||||
private final Stage window;
|
||||
private final Settings settings;
|
||||
private final boolean trayMenuInitialized;
|
||||
private final boolean trayMenuSupported;
|
||||
private final Optional<AutoStartStrategy> autoStartStrategy;
|
||||
private final Optional<AutoStartProvider> autoStartProvider;
|
||||
private final ObjectProperty<SelectedPreferencesTab> selectedTabProperty;
|
||||
private final LicenseHolder licenseHolder;
|
||||
private final ExecutorService executor;
|
||||
private final ResourceBundle resourceBundle;
|
||||
private final Application application;
|
||||
private final Environment environment;
|
||||
@@ -53,6 +52,8 @@ public class GeneralPreferencesController implements FxController {
|
||||
private final ErrorComponent.Builder errorComponent;
|
||||
public ChoiceBox<UiTheme> themeChoiceBox;
|
||||
public ChoiceBox<KeychainBackend> keychainBackendChoiceBox;
|
||||
public CheckBox showMinimizeButtonCheckbox;
|
||||
public CheckBox showTrayIconCheckbox;
|
||||
public CheckBox startHiddenCheckbox;
|
||||
public CheckBox debugModeCheckbox;
|
||||
public CheckBox autoStartCheckbox;
|
||||
@@ -60,16 +61,17 @@ public class GeneralPreferencesController implements FxController {
|
||||
public RadioButton nodeOrientationLtr;
|
||||
public RadioButton nodeOrientationRtl;
|
||||
|
||||
|
||||
@Inject
|
||||
GeneralPreferencesController(@PreferencesWindow Stage window, Settings settings, @Named("trayMenuSupported") boolean trayMenuSupported, Optional<AutoStartStrategy> autoStartStrategy, Set<KeychainAccessProvider> keychainAccessProviders, ObjectProperty<SelectedPreferencesTab> selectedTabProperty, LicenseHolder licenseHolder, ExecutorService executor, ResourceBundle resourceBundle, Application application, Environment environment, ErrorComponent.Builder errorComponent) {
|
||||
GeneralPreferencesController(@PreferencesWindow Stage window, Settings settings, TrayMenuComponent trayMenu, Optional<AutoStartProvider> autoStartProvider, Set<KeychainAccessProvider> keychainAccessProviders, ObjectProperty<SelectedPreferencesTab> selectedTabProperty, LicenseHolder licenseHolder, ResourceBundle resourceBundle, Application application, Environment environment, ErrorComponent.Builder errorComponent) {
|
||||
this.window = window;
|
||||
this.settings = settings;
|
||||
this.trayMenuSupported = trayMenuSupported;
|
||||
this.autoStartStrategy = autoStartStrategy;
|
||||
this.trayMenuInitialized = trayMenu.isInitialized();
|
||||
this.trayMenuSupported = trayMenu.isSupported();
|
||||
this.autoStartProvider = autoStartProvider;
|
||||
this.keychainAccessProviders = keychainAccessProviders;
|
||||
this.selectedTabProperty = selectedTabProperty;
|
||||
this.licenseHolder = licenseHolder;
|
||||
this.executor = executor;
|
||||
this.resourceBundle = resourceBundle;
|
||||
this.application = application;
|
||||
this.environment = environment;
|
||||
@@ -85,15 +87,15 @@ public class GeneralPreferencesController implements FxController {
|
||||
themeChoiceBox.valueProperty().bindBidirectional(settings.theme());
|
||||
themeChoiceBox.setConverter(new UiThemeConverter(resourceBundle));
|
||||
|
||||
showMinimizeButtonCheckbox.selectedProperty().bindBidirectional(settings.showMinimizeButton());
|
||||
|
||||
showTrayIconCheckbox.selectedProperty().bindBidirectional(settings.showTrayIcon());
|
||||
|
||||
startHiddenCheckbox.selectedProperty().bindBidirectional(settings.startHidden());
|
||||
|
||||
debugModeCheckbox.selectedProperty().bindBidirectional(settings.debugMode());
|
||||
|
||||
autoStartStrategy.ifPresent(autoStart -> {
|
||||
autoStart.isAutoStartEnabled().thenAccept(enabled -> {
|
||||
Platform.runLater(() -> autoStartCheckbox.setSelected(enabled));
|
||||
});
|
||||
});
|
||||
autoStartProvider.ifPresent(autoStart -> autoStartCheckbox.setSelected(autoStart.isEnabled()));
|
||||
|
||||
nodeOrientationLtr.setSelected(settings.userInterfaceOrientation().get() == NodeOrientation.LEFT_TO_RIGHT);
|
||||
nodeOrientationRtl.setSelected(settings.userInterfaceOrientation().get() == NodeOrientation.RIGHT_TO_LEFT);
|
||||
@@ -109,12 +111,16 @@ public class GeneralPreferencesController implements FxController {
|
||||
return Arrays.stream(KeychainBackend.values()).filter(value -> namesOfAvailableProviders.contains(value.getProviderClass())).toArray(KeychainBackend[]::new);
|
||||
}
|
||||
|
||||
public boolean isTrayMenuInitialized() {
|
||||
return trayMenuInitialized;
|
||||
}
|
||||
|
||||
public boolean isTrayMenuSupported() {
|
||||
return this.trayMenuSupported;
|
||||
return trayMenuSupported;
|
||||
}
|
||||
|
||||
public boolean isAutoStartSupported() {
|
||||
return autoStartStrategy.isPresent();
|
||||
return autoStartProvider.isPresent();
|
||||
}
|
||||
|
||||
private void toggleNodeOrientation(@SuppressWarnings("unused") ObservableValue<? extends Toggle> observable, @SuppressWarnings("unused") Toggle oldValue, Toggle newValue) {
|
||||
@@ -129,15 +135,19 @@ public class GeneralPreferencesController implements FxController {
|
||||
|
||||
@FXML
|
||||
public void toggleAutoStart() {
|
||||
autoStartStrategy.ifPresent(autoStart -> {
|
||||
autoStartProvider.ifPresent(autoStart -> {
|
||||
boolean enableAutoStart = autoStartCheckbox.isSelected();
|
||||
Task<Void> toggleTask = new ToggleAutoStartTask(autoStart, enableAutoStart);
|
||||
toggleTask.setOnFailed(event -> {
|
||||
try {
|
||||
if (enableAutoStart) {
|
||||
autoStart.enable();
|
||||
} else {
|
||||
autoStart.disable();
|
||||
}
|
||||
} catch (ToggleAutoStartFailedException e) {
|
||||
autoStartCheckbox.setSelected(!enableAutoStart); // restore previous state
|
||||
LOG.error("Failed to toggle autostart.", event.getSource().getException());
|
||||
errorComponent.cause(event.getSource().getException()).window(window).returnToScene(window.getScene()).build().showErrorScene();
|
||||
});
|
||||
executor.execute(toggleTask);
|
||||
LOG.error("Failed to toggle autostart.", e);
|
||||
errorComponent.cause(e).window(window).returnToScene(window.getScene()).build().showErrorScene();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -175,6 +185,7 @@ public class GeneralPreferencesController implements FxController {
|
||||
public UiTheme fromString(String string) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class KeychainBackendConverter extends StringConverter<KeychainBackend> {
|
||||
@@ -194,29 +205,6 @@ public class GeneralPreferencesController implements FxController {
|
||||
public KeychainBackend fromString(String string) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class ToggleAutoStartTask extends Task<Void> {
|
||||
|
||||
private final AutoStartStrategy autoStart;
|
||||
private final boolean enable;
|
||||
|
||||
public ToggleAutoStartTask(AutoStartStrategy autoStart, boolean enable) {
|
||||
this.autoStart = autoStart;
|
||||
this.enable = enable;
|
||||
|
||||
setOnFailed(event -> LOG.error("Failed to toggle Autostart", getException()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void call() throws Exception {
|
||||
if (enable) {
|
||||
autoStart.enableAutoStart();
|
||||
} else {
|
||||
autoStart.disableAutoStart();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ import javafx.stage.Stage;
|
||||
import java.util.Map;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
@Module(includes = {AutoStartModule.class})
|
||||
@Module
|
||||
abstract class PreferencesModule {
|
||||
|
||||
@Provides
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.cryptomator.ui.traymenu;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
import org.cryptomator.integrations.uiappearance.Theme;
|
||||
import org.cryptomator.integrations.uiappearance.UiAppearanceException;
|
||||
@@ -22,6 +23,7 @@ public class TrayIconController {
|
||||
private final Optional<UiAppearanceProvider> appearanceProvider;
|
||||
private final TrayMenuController trayMenuController;
|
||||
private final TrayIcon trayIcon;
|
||||
private volatile boolean initialized;
|
||||
|
||||
@Inject
|
||||
TrayIconController(TrayImageFactory imageFactory, TrayMenuController trayMenuController, Optional<UiAppearanceProvider> appearanceProvider) {
|
||||
@@ -31,7 +33,9 @@ public class TrayIconController {
|
||||
this.trayIcon = new TrayIcon(imageFactory.loadImage(), "Cryptomator", trayMenuController.getMenu());
|
||||
}
|
||||
|
||||
public void initializeTrayIcon() {
|
||||
public synchronized void initializeTrayIcon() throws IllegalStateException {
|
||||
Preconditions.checkState(!initialized);
|
||||
|
||||
appearanceProvider.ifPresent(appearanceProvider -> {
|
||||
try {
|
||||
appearanceProvider.addListener(this::systemInterfaceThemeChanged);
|
||||
@@ -53,10 +57,15 @@ public class TrayIconController {
|
||||
}
|
||||
|
||||
trayMenuController.initTrayMenu();
|
||||
|
||||
this.initialized = true;
|
||||
}
|
||||
|
||||
private void systemInterfaceThemeChanged(Theme theme) {
|
||||
trayIcon.setImage(imageFactory.loadImage()); // TODO refactor "theme" is re-queried in loadImage()
|
||||
}
|
||||
|
||||
public boolean isInitialized() {
|
||||
return initialized;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
*******************************************************************************/
|
||||
package org.cryptomator.ui.traymenu;
|
||||
|
||||
import dagger.Lazy;
|
||||
import dagger.Subcomponent;
|
||||
|
||||
import java.awt.SystemTray;
|
||||
@@ -13,11 +14,30 @@ import java.awt.SystemTray;
|
||||
@Subcomponent
|
||||
public interface TrayMenuComponent {
|
||||
|
||||
TrayIconController trayIconController();
|
||||
Lazy<TrayIconController> trayIconController();
|
||||
|
||||
default void addIconToSystemTray() {
|
||||
assert SystemTray.isSupported();
|
||||
trayIconController().initializeTrayIcon();
|
||||
/**
|
||||
* @return <code>true</code> if a tray icon can be installed
|
||||
*/
|
||||
default boolean isSupported() {
|
||||
return SystemTray.isSupported();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return <code>true</code> if a tray icon has been installed
|
||||
*/
|
||||
default boolean isInitialized() {
|
||||
return isSupported() && trayIconController().get().isInitialized();
|
||||
}
|
||||
|
||||
/**
|
||||
* Installs a tray icon to the system tray.
|
||||
*
|
||||
* @throws IllegalStateException If already added
|
||||
*/
|
||||
default void initializeTrayIcon() throws IllegalStateException {
|
||||
assert isSupported();
|
||||
trayIconController().get().initializeTrayIcon();
|
||||
}
|
||||
|
||||
@Subcomponent.Builder
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.cryptomator.ui.traymenu;
|
||||
|
||||
import org.cryptomator.common.vaults.Vault;
|
||||
import org.cryptomator.ui.fxapp.FxApplication;
|
||||
import org.cryptomator.ui.launcher.AppLifecycleListener;
|
||||
import org.cryptomator.ui.launcher.FxApplicationStarter;
|
||||
import org.cryptomator.ui.preferences.SelectedPreferencesTab;
|
||||
@@ -103,32 +104,36 @@ class TrayMenuController {
|
||||
return actionEvent -> consumer.accept(vault);
|
||||
}
|
||||
|
||||
private void unlockVault(Vault vault) {
|
||||
fxApplicationStarter.get(true).thenAccept(app -> app.startUnlockWorkflow(vault, Optional.empty()));
|
||||
}
|
||||
|
||||
private void lockVault(Vault vault) {
|
||||
fxApplicationStarter.get(true).thenAccept(app -> app.getVaultService().lock(vault, false));
|
||||
}
|
||||
|
||||
private void lockAllVaults(ActionEvent actionEvent) {
|
||||
fxApplicationStarter.get(true).thenAccept(app -> app.getVaultService().lockAll(vaults.filtered(Vault::isUnlocked), false));
|
||||
}
|
||||
|
||||
private void revealVault(Vault vault) {
|
||||
fxApplicationStarter.get(true).thenAccept(app -> app.getVaultService().reveal(vault));
|
||||
}
|
||||
|
||||
void showMainWindow(@SuppressWarnings("unused") ActionEvent actionEvent) {
|
||||
fxApplicationStarter.get(true).thenAccept(app -> app.showMainWindow());
|
||||
}
|
||||
|
||||
private void showPreferencesWindow(@SuppressWarnings("unused") EventObject actionEvent) {
|
||||
fxApplicationStarter.get(true).thenAccept(app -> app.showPreferencesWindow(SelectedPreferencesTab.ANY));
|
||||
}
|
||||
|
||||
private void quitApplication(EventObject actionEvent) {
|
||||
appLifecycle.quit();
|
||||
}
|
||||
|
||||
private void unlockVault(Vault vault) {
|
||||
showMainAppAndThen(app -> app.startUnlockWorkflow(vault, Optional.empty()));
|
||||
}
|
||||
|
||||
private void lockVault(Vault vault) {
|
||||
showMainAppAndThen(app -> app.startLockWorkflow(vault, Optional.empty()));
|
||||
}
|
||||
|
||||
private void lockAllVaults(ActionEvent actionEvent) {
|
||||
showMainAppAndThen(app -> app.getVaultService().lockAll(vaults.filtered(Vault::isUnlocked), false));
|
||||
}
|
||||
|
||||
private void revealVault(Vault vault) {
|
||||
showMainAppAndThen(app -> app.getVaultService().reveal(vault));
|
||||
}
|
||||
|
||||
void showMainWindow(@SuppressWarnings("unused") ActionEvent actionEvent) {
|
||||
showMainAppAndThen(app -> app.showMainWindow());
|
||||
}
|
||||
|
||||
private void showPreferencesWindow(@SuppressWarnings("unused") EventObject actionEvent) {
|
||||
showMainAppAndThen(app -> app.showPreferencesWindow(SelectedPreferencesTab.ANY));
|
||||
}
|
||||
|
||||
private void showMainAppAndThen(Consumer<FxApplication> action) {
|
||||
fxApplicationStarter.get().thenAccept(action);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
37
main/ui/src/main/resources/fxml/lock_failed.fxml
Normal file
37
main/ui/src/main/resources/fxml/lock_failed.fxml
Normal file
@@ -0,0 +1,37 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import org.cryptomator.ui.controls.FontAwesome5IconView?>
|
||||
<?import org.cryptomator.ui.controls.FormattedLabel?>
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.control.Button?>
|
||||
<?import javafx.scene.control.Label?>
|
||||
<?import javafx.scene.layout.HBox?>
|
||||
<?import javafx.scene.layout.StackPane?>
|
||||
<?import javafx.scene.layout.VBox?>
|
||||
<?import javafx.scene.shape.Circle?>
|
||||
<VBox xmlns:fx="http://javafx.com/fxml"
|
||||
xmlns="http://javafx.com/javafx"
|
||||
fx:controller="org.cryptomator.ui.lock.LockFailedController"
|
||||
minWidth="400"
|
||||
maxWidth="400"
|
||||
minHeight="145"
|
||||
spacing="12">
|
||||
<padding>
|
||||
<Insets topRightBottomLeft="12"/>
|
||||
</padding>
|
||||
<children>
|
||||
<HBox spacing="12" alignment="CENTER_LEFT" VBox.vgrow="ALWAYS">
|
||||
<StackPane alignment="CENTER" HBox.hgrow="NEVER">
|
||||
<Circle styleClass="glyph-icon-red" radius="24"/>
|
||||
<FontAwesome5IconView styleClass="glyph-icon-white" glyph="TIMES" glyphSize="24"/>
|
||||
</StackPane>
|
||||
<VBox spacing="6">
|
||||
<Label styleClass="label-large" text="%lock.fail.heading"/>
|
||||
<FormattedLabel format="%lock.fail.message" arg1="${controller.vaultName}" wrapText="true"/>
|
||||
</VBox>
|
||||
</HBox>
|
||||
<VBox alignment="BOTTOM_CENTER" VBox.vgrow="ALWAYS">
|
||||
<Button text="OK" defaultButton="false" VBox.vgrow="ALWAYS" cancelButton="true" onAction="#close"/>
|
||||
</VBox>
|
||||
</children>
|
||||
</VBox>
|
||||
45
main/ui/src/main/resources/fxml/lock_forced.fxml
Normal file
45
main/ui/src/main/resources/fxml/lock_forced.fxml
Normal file
@@ -0,0 +1,45 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import org.cryptomator.ui.controls.FontAwesome5IconView?>
|
||||
<?import org.cryptomator.ui.controls.FormattedLabel?>
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.control.Button?>
|
||||
<?import javafx.scene.control.ButtonBar?>
|
||||
<?import javafx.scene.control.Label?>
|
||||
<?import javafx.scene.layout.HBox?>
|
||||
<?import javafx.scene.layout.StackPane?>
|
||||
<?import javafx.scene.layout.VBox?>
|
||||
<?import javafx.scene.shape.Circle?>
|
||||
<VBox xmlns:fx="http://javafx.com/fxml"
|
||||
xmlns="http://javafx.com/javafx"
|
||||
fx:controller="org.cryptomator.ui.lock.LockForcedController"
|
||||
minWidth="400"
|
||||
maxWidth="400"
|
||||
minHeight="145"
|
||||
spacing="12">
|
||||
<padding>
|
||||
<Insets topRightBottomLeft="12"/>
|
||||
</padding>
|
||||
<children>
|
||||
<HBox spacing="12" alignment="CENTER_LEFT" VBox.vgrow="ALWAYS">
|
||||
<StackPane alignment="CENTER" HBox.hgrow="NEVER">
|
||||
<Circle styleClass="glyph-icon-orange" radius="24"/>
|
||||
<FontAwesome5IconView styleClass="glyph-icon-white" glyph="EXCLAMATION" glyphSize="24"/>
|
||||
</StackPane>
|
||||
<VBox spacing="6">
|
||||
<Label styleClass="label-large" text="%lock.forced.heading"/>
|
||||
<FormattedLabel format="%lock.forced.message" arg1="${controller.vaultName}" wrapText="true"/>
|
||||
</VBox>
|
||||
</HBox>
|
||||
|
||||
<VBox alignment="BOTTOM_CENTER" VBox.vgrow="ALWAYS">
|
||||
<ButtonBar buttonMinWidth="120" buttonOrder="+CI">
|
||||
<buttons>
|
||||
<Button text="%generic.button.cancel" ButtonBar.buttonData="CANCEL_CLOSE" defaultButton="true" cancelButton="true" onAction="#cancel"/>
|
||||
<!-- TODO: third button with retry? -->
|
||||
<Button text="%lock.forced.confirmBtn" ButtonBar.buttonData="FINISH" onAction="#confirmForcedLock"/>
|
||||
</buttons>
|
||||
</ButtonBar>
|
||||
</VBox>
|
||||
</children>
|
||||
</VBox>
|
||||
@@ -54,7 +54,7 @@
|
||||
<Tooltip text="%main.preferencesBtn.tooltip"/>
|
||||
</tooltip>
|
||||
</Button>
|
||||
<Button contentDisplay="GRAPHIC_ONLY" mnemonicParsing="false" onAction="#minimize" focusTraversable="false" visible="${!controller.minimizeToSysTray}" managed="${!controller.minimizeToSysTray}">
|
||||
<Button contentDisplay="GRAPHIC_ONLY" mnemonicParsing="false" onAction="#minimize" focusTraversable="false" visible="${controller.showMinimizeButton}" managed="${controller.showMinimizeButton}">
|
||||
<graphic>
|
||||
<FontAwesome5IconView glyph="WINDOW_MINIMIZE" glyphSize="12"/>
|
||||
</graphic>
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
</ImageView>
|
||||
<VBox spacing="3" HBox.hgrow="ALWAYS" alignment="CENTER_LEFT">
|
||||
<FormattedLabel styleClass="label-large" format="Cryptomator %s" arg1="${controller.applicationVersion}"/>
|
||||
<Label text="© 2016 – 2020 Skymatic GmbH"/>
|
||||
<Label text="© 2016 – 2021 Skymatic GmbH"/>
|
||||
</VBox>
|
||||
</HBox>
|
||||
|
||||
|
||||
@@ -32,7 +32,11 @@
|
||||
<RadioButton fx:id="nodeOrientationRtl" text="%preferences.general.interfaceOrientation.rtl" alignment="CENTER_RIGHT" toggleGroup="${nodeOrientation}"/>
|
||||
</HBox>
|
||||
|
||||
<CheckBox fx:id="startHiddenCheckbox" text="%preferences.general.startHidden" visible="${controller.trayMenuSupported}" managed="${controller.trayMenuSupported}"/>
|
||||
<CheckBox fx:id="showMinimizeButtonCheckbox" text="%preferences.general.showMinimizeButton" visible="${controller.trayMenuInitialized}" managed="${controller.trayMenuInitialized}"/>
|
||||
|
||||
<CheckBox fx:id="showTrayIconCheckbox" text="%preferences.general.showTrayIcon" visible="${controller.trayMenuSupported}" managed="${controller.trayMenuSupported}"/>
|
||||
|
||||
<CheckBox fx:id="startHiddenCheckbox" text="%preferences.general.startHidden" />
|
||||
|
||||
<HBox spacing="6" alignment="CENTER_LEFT">
|
||||
<CheckBox fx:id="debugModeCheckbox" text="%preferences.general.debugLogging"/>
|
||||
|
||||
@@ -108,6 +108,15 @@ unlock.error.heading=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.
|
||||
|
||||
# Lock
|
||||
## Force
|
||||
lock.forced.heading=Graceful lock failed
|
||||
lock.forced.message=Locking "%s" was blocked by pending operations or open files. You can force lock this vault, however interrupting I/O may result in the loss of unsaved data.
|
||||
lock.forced.confirmBtn=Force Lock
|
||||
## Failure
|
||||
lock.fail.heading=Locking vault failed.
|
||||
lock.fail.message=Vault "%s" could not be locked. Ensure unsaved work is saved elsewhere and important Read/Write operations are finished. In order to close the vault, kill the Cryptomator process.
|
||||
|
||||
# Migration
|
||||
migration.title=Upgrade Vault
|
||||
## Start
|
||||
@@ -141,6 +150,8 @@ preferences.general.theme.automatic=Automatic
|
||||
preferences.general.theme.light=Light
|
||||
preferences.general.theme.dark=Dark
|
||||
preferences.general.unlockThemes=Unlock dark mode
|
||||
preferences.general.showMinimizeButton=Show minimize button
|
||||
preferences.general.showTrayIcon=Show tray icon (requires restart)
|
||||
preferences.general.startHidden=Hide window when starting Cryptomator
|
||||
preferences.general.debugLogging=Enable debug logging
|
||||
preferences.general.debugDirectory=Reveal log files
|
||||
|
||||
@@ -102,10 +102,17 @@ unlock.success.message=تم فتح المخزن "%s" بنجاح! يمكنك ال
|
||||
unlock.success.rememberChoice=تذكر اختياري ولا تظهر هذا مرة أخرى
|
||||
unlock.success.revealBtn=افتح الحافظة
|
||||
## Failure
|
||||
unlock.error.heading=غير قادر على فتح الخزنة
|
||||
### Invalid Mount Point
|
||||
unlock.error.invalidMountPoint.notExisting=نقطة التحميل ليست مجلد فارغ أو غير موجودة: %s
|
||||
unlock.error.invalidMountPoint.existing=نقطة/مجلد التحميل موجود بالفعل أو المجلد الأصل مفقود: %s
|
||||
|
||||
# Lock
|
||||
## Force
|
||||
lock.forced.confirmBtn=فرض القفل
|
||||
## Failure
|
||||
lock.fail.heading=فشلت عملية اقفال الخزنة.
|
||||
|
||||
# Migration
|
||||
migration.title=ترقية الحافظة
|
||||
## Start
|
||||
@@ -171,8 +178,12 @@ preferences.donationKey.getDonationKey=الحصول على مفتاح تبرع
|
||||
preferences.about=حول البرنامج
|
||||
|
||||
# Vault Statistics
|
||||
stats.cacheHitRate=معدل استخدام الكاش
|
||||
## Read
|
||||
stats.read.throughput.idle=قراءة: خامل
|
||||
stats.decr.total.data.none=تم فك تشفير البيانات:-
|
||||
## Write
|
||||
stats.encr.total.data.none=البيانات المشفرة: -
|
||||
|
||||
# Main Window
|
||||
main.closeBtn.tooltip=إغلاق
|
||||
@@ -202,9 +213,11 @@ main.vaultDetail.accessLocation=يمكن الوصول إلى محتويات مخ
|
||||
main.vaultDetail.revealBtn=اظهار القرص
|
||||
main.vaultDetail.lockBtn=قفل
|
||||
main.vaultDetail.bytesPerSecondRead=قراءة:
|
||||
main.vaultDetail.bytesPerSecondWritten=كتابة:
|
||||
main.vaultDetail.throughput.idle=خمول
|
||||
main.vaultDetail.throughput.kbps=%.1f كيلوبايت/ث
|
||||
main.vaultDetail.throughput.mbps=%.1f ميجابايت/ث
|
||||
main.vaultDetail.stats=إحصائيات الخزنة
|
||||
### Missing
|
||||
main.vaultDetail.missing.info=لم يتمكن Cryptomator من العثور على خزنة في هذا المسار.
|
||||
main.vaultDetail.missing.recheck=إعادة الفحص
|
||||
|
||||
@@ -106,6 +106,10 @@ unlock.error.heading=Sef nije moguće otključati
|
||||
### Invalid Mount Point
|
||||
unlock.error.invalidMountPoint.notExisting=Tačka postavljanja "%s" nije direktorij, nije prazna ili ne postoji.
|
||||
|
||||
# Lock
|
||||
## Force
|
||||
## Failure
|
||||
|
||||
# Migration
|
||||
## Start
|
||||
## Run
|
||||
|
||||
@@ -17,6 +17,7 @@ generic.error.title=S'ha produït un error inesperat
|
||||
generic.error.instruction=Això no hauria d'haver passat. Si us plau, informeu del text de l'error i inclogueu una descripció de quins passos han dut a aquest error.
|
||||
|
||||
# Defaults
|
||||
defaults.vault.vaultName=Caixa forta
|
||||
|
||||
# Tray Menu
|
||||
traymenu.showMainWindow=Mostra
|
||||
@@ -44,6 +45,7 @@ addvaultwizard.new.directoryPickerLabel=Ubicació personalitzada
|
||||
addvaultwizard.new.directoryPickerButton=Trieu…
|
||||
addvaultwizard.new.directoryPickerTitle=Seleccioneu el directori
|
||||
addvaultwizard.new.fileAlreadyExists=No es pot crear una caixa forta en aquest camí perquè ja hi ha algun objecte.
|
||||
addvaultwizard.new.locationDoesNotExist=No ha estat possible crear la caixa forta en aquest camí perquè, si més no, un component no existeix.
|
||||
addvaultwizard.new.invalidName=El nom de la caixa forta no és vàlid. Si us plau, escribiu un mom de directori amb caràcters estàndard.
|
||||
### Password
|
||||
addvaultwizard.new.createVaultBtn=Crea la caixa forta
|
||||
@@ -100,10 +102,20 @@ unlock.success.message="%s" s'ha desbloquejat correctament! Ja es pot accedir a
|
||||
unlock.success.rememberChoice=Recorda l'elecció. No ho tornis a mostrar.
|
||||
unlock.success.revealBtn=Mostra la caixa forta
|
||||
## Failure
|
||||
unlock.error.heading=No ha estat possible desblocar la caixa forta
|
||||
### Invalid Mount Point
|
||||
unlock.error.invalidMountPoint.notExisting=El punt de muntatge no és un directori buit, o no existeix: %s
|
||||
unlock.error.invalidMountPoint.existing=El punt de muntatge o la carpeta ja existeix, o no es pot accedir al directori superior: %s
|
||||
|
||||
# Lock
|
||||
## Force
|
||||
lock.forced.heading=Ha fallat el blocatge
|
||||
lock.forced.message=No s'ha blocat "%s" perquè hi ha operacions pendents o fitxers oberts. Podeu forçar-ne el blocatge però heu de saber que interrompre l'entrada/sortida pot produir la pèrdua de dades.
|
||||
lock.forced.confirmBtn=Força el blocatge
|
||||
## Failure
|
||||
lock.fail.heading=Ha fallat el blocatge de la caixa forta.
|
||||
lock.fail.message=La caixa forta "%s" no s'ha pogut blocar. Assegureu-vos que el treball s'ha desat en algun altre lloc i que les operacions de lectura/escriptura han acabat. Per tal de tancar la caixa, mateu el procés Cryptomator.
|
||||
|
||||
# Migration
|
||||
migration.title=Actualitza la caixa forta
|
||||
## Start
|
||||
@@ -133,13 +145,21 @@ preferences.title=Preferències
|
||||
## General
|
||||
preferences.general=General
|
||||
preferences.general.theme=Apariència
|
||||
preferences.general.theme.automatic=Automàtic
|
||||
preferences.general.theme.light=Clar
|
||||
preferences.general.theme.dark=Fosc
|
||||
preferences.general.unlockThemes=Desbloqueja el tema fosc
|
||||
preferences.general.startHidden=Amaga la finestra al iniciar Cryptomator
|
||||
preferences.general.showMinimizeButton=Mostra el botó de minimitzar
|
||||
preferences.general.showTrayIcon=Mostra la icona en la barra (cal reiniciar)
|
||||
preferences.general.startHidden=Amaga la finestra quan s'inicia Cryptomator
|
||||
preferences.general.debugLogging=Habilita el registre de depuració
|
||||
preferences.general.debugDirectory=Mostra els fitxers de registres
|
||||
preferences.general.autoStart=Executa Cryptomator en engegar el sistema
|
||||
preferences.general.keychainBackend=Desar contrasenyes amb
|
||||
preferences.general.keychainBackend.org.cryptomator.linux.keychain.SecretServiceKeychainAccess=Anell de claus de Gnome
|
||||
preferences.general.keychainBackend.org.cryptomator.linux.keychain.KDEWalletKeychainAccess=Cartera de KDE
|
||||
preferences.general.keychainBackend.org.cryptomator.macos.keychain.MacSystemKeychainAccess=Accés a clauers macOS
|
||||
preferences.general.keychainBackend.org.cryptomator.windows.keychain.WindowsProtectedKeychainAccess=Windows Data Protection
|
||||
preferences.general.interfaceOrientation=Orientació de la interfície
|
||||
preferences.general.interfaceOrientation.ltr=Esquerra a dreta
|
||||
preferences.general.interfaceOrientation.rtl=Dreta a esquerra
|
||||
@@ -163,38 +183,73 @@ preferences.donationKey.getDonationKey=Obtingau una clau de donació
|
||||
preferences.about=Quant a
|
||||
|
||||
# Vault Statistics
|
||||
stats.title=Estadístiques per a %s
|
||||
stats.cacheHitRate=Relació d'encerts de la memòria cau
|
||||
## Read
|
||||
stats.read.throughput.idle=Llegit: inactiu
|
||||
stats.read.throughput.kibs=Llegit: %.2f kiB/s
|
||||
stats.read.throughput.mibs=Llegit: %.2f MiB/s
|
||||
stats.read.total.data.none=Dades llegides: -
|
||||
stats.read.total.data.kib=Dades llegides: %.1f kiB
|
||||
stats.read.total.data.mib=Dades llegides: %.1f MiB
|
||||
stats.read.total.data.gib=Dades llegides: %.1f GiB
|
||||
stats.decr.total.data.none=Dades desxifrades: -
|
||||
stats.decr.total.data.kib=Dades desxifrades: %.1f kiB
|
||||
stats.decr.total.data.mib=Dades desxifrades: %.1f MiB
|
||||
stats.decr.total.data.gib=Dades desxifrades: %.1f GiB
|
||||
stats.read.accessCount=Lectures en total: %d
|
||||
## Write
|
||||
stats.write.throughput.idle=Escriu: inactiu
|
||||
stats.write.throughput.kibs=Escriu: %.2f kiB/s
|
||||
stats.write.throughput.mibs=Escriu: %.2f MiB/s
|
||||
stats.write.total.data.none=Dades llegides: -
|
||||
stats.write.total.data.kib=Dades escrites: %.1f kiB
|
||||
stats.write.total.data.mib=Dades escrites: %.1f MiB
|
||||
stats.write.total.data.gib=Dades escrites: %.1f GiB
|
||||
stats.encr.total.data.none=Dades xifrades: -
|
||||
stats.encr.total.data.kib=Dades xifrades: %.1f kiB
|
||||
stats.encr.total.data.mib=Dades xifrades: %.1f MiB
|
||||
stats.encr.total.data.gib=Dades xifrades: %.1f GiB
|
||||
stats.write.accessCount=Total escrits: %d
|
||||
|
||||
# Main Window
|
||||
main.closeBtn.tooltip=Tanca
|
||||
main.minimizeBtn.tooltip=Minimitza
|
||||
main.preferencesBtn.tooltip=Preferències
|
||||
main.debugModeEnabled.tooltip=Mode depuració activat
|
||||
main.donationKeyMissing.tooltip=Si us plau, considereu fer una donació
|
||||
## Drag 'n' Drop
|
||||
main.dropZone.dropVault=Afegeix aquesta caixa forta
|
||||
main.dropZone.unknownDragboardContent=Si voleu afegir una caixa forta, arrossegueu-la a aquesta finestra
|
||||
## Vault List
|
||||
main.vaultlist.emptyList.onboardingInstruction=Feu clic aquí per afegir una caixa forta
|
||||
main.vaultlist.contextMenu.remove=Elimina la caixa forta…
|
||||
main.vaultlist.addVaultBtn=Afegir una caixa forta
|
||||
## Vault Detail
|
||||
### Welcome
|
||||
main.vaultDetail.welcomeOnboarding=Gràcies per escollir Cryptomator per protegir els vostres fitxers. Si vos cal ajuda, llegiu les nostres guies per donar els Primers passos:
|
||||
### Locked
|
||||
main.vaultDetail.lockedStatus=BLOQUEJADA
|
||||
main.vaultDetail.unlockBtn=Desbloca…
|
||||
main.vaultDetail.unlockNowBtn=Desbloqueja ara
|
||||
main.vaultDetail.optionsBtn=Opcions de la caixa forta
|
||||
main.vaultDetail.passwordSavedInKeychain=Contrasenya desada
|
||||
### Unlocked
|
||||
main.vaultDetail.unlockedStatus=DESBLOQUEJADA
|
||||
main.vaultDetail.accessLocation=Els continguts de la vostra caixa forta són accessibles aquí:
|
||||
main.vaultDetail.revealBtn=Mostra la unitat
|
||||
main.vaultDetail.lockBtn=Bloqueja
|
||||
main.vaultDetail.bytesPerSecondRead=Lectura:
|
||||
main.vaultDetail.bytesPerSecondWritten=Escriu:
|
||||
main.vaultDetail.throughput.idle=inactiu
|
||||
main.vaultDetail.throughput.kbps=%.1f kiB/s
|
||||
main.vaultDetail.throughput.mbps=%.1f MiB/s
|
||||
main.vaultDetail.stats=Estadístiques de la caixa forta
|
||||
### Missing
|
||||
main.vaultDetail.missing.info=Cryptomator no ha trobat una caixa forta en aquest camí.
|
||||
main.vaultDetail.missing.recheck=Torna a comprovar
|
||||
main.vaultDetail.missing.remove=Eliminar de la llista de la caixa forta…
|
||||
main.vaultDetail.missing.changeLocation=Canvia la localització de la caixa forta…
|
||||
### Needs Migration
|
||||
main.vaultDetail.migrateButton=Actualitza la caixa forta
|
||||
main.vaultDetail.migratePrompt=Per accedir a la vostra caixa forta abans cal actualitzar-la al nou format
|
||||
@@ -213,7 +268,7 @@ wrongFileAlert.link=Per rebre assistència, visiteu
|
||||
## General
|
||||
vaultOptions.general=General
|
||||
vaultOptions.general.vaultName=Nom de la caixa forta
|
||||
vaultOptions.general.unlockAfterStartup=Desbloqueja la caixa forta al iniciar Cryptomator
|
||||
vaultOptions.general.unlockAfterStartup=Desbloqueja la caixa forta quan s'inicia Cryptomator
|
||||
vaultOptions.general.actionAfterUnlock=Després d'un desbloqueig correcte
|
||||
vaultOptions.general.actionAfterUnlock.ignore=No facis res
|
||||
vaultOptions.general.actionAfterUnlock.reveal=Mostra la unitat
|
||||
@@ -232,6 +287,7 @@ vaultOptions.mount.mountPoint.directoryPickerTitle=Esculliu un directori buit
|
||||
## Master Key
|
||||
vaultOptions.masterkey=Contrasenya
|
||||
vaultOptions.masterkey.changePasswordBtn=Canvi de contrasenya
|
||||
vaultOptions.masterkey.forgetSavedPasswordBtn=Oblida la contrasenya desada
|
||||
vaultOptions.masterkey.recoveryKeyExpanation=La clau de recuperació és l'unic mitjà de restaurar l'accès a la caixa forta en cas de perdre la contrasenya.
|
||||
vaultOptions.masterkey.showRecoveryKeyBtn=Mostra la clau de recuperació
|
||||
vaultOptions.masterkey.recoverPasswordBtn=Recupera la contrasenya
|
||||
|
||||
@@ -107,6 +107,10 @@ unlock.error.heading=Nelze odemknout trezor
|
||||
unlock.error.invalidMountPoint.notExisting=Připojovací bod %s není složkou, není prázdný nebo neexistuje.
|
||||
unlock.error.invalidMountPoint.existing=Připojovací bod %s již existuje nebo nadřazená složka chybí.
|
||||
|
||||
# Lock
|
||||
## Force
|
||||
## Failure
|
||||
|
||||
# Migration
|
||||
migration.title=Upgrade trezoru
|
||||
## Start
|
||||
@@ -140,6 +144,8 @@ preferences.general.theme.automatic=Automaticky
|
||||
preferences.general.theme.light=Světlý
|
||||
preferences.general.theme.dark=Tmavý
|
||||
preferences.general.unlockThemes=Odemknout tmavý režim
|
||||
preferences.general.showMinimizeButton=Zobrazit tlačítko minimalizovat
|
||||
preferences.general.showTrayIcon=Zobrazit ikonu v liště (vyžaduje restart)
|
||||
preferences.general.startHidden=Skrýt okno Cryptomatoru při spuštění
|
||||
preferences.general.debugLogging=Ladicí režim
|
||||
preferences.general.debugDirectory=Ukázat soubory se záznamy událostí (log)
|
||||
|
||||
@@ -107,6 +107,15 @@ unlock.error.heading=Tresor konnte nicht entsperrt werden
|
||||
unlock.error.invalidMountPoint.notExisting=Einhängepunkt ist kein leeres Verzeichnis oder existiert nicht: %s
|
||||
unlock.error.invalidMountPoint.existing=Einhängepunkt/Ordner bereits vorhanden oder übergeordneter Ordner fehlt: %s
|
||||
|
||||
# Lock
|
||||
## Force
|
||||
lock.forced.heading=Sperren fehlgeschlagen
|
||||
lock.forced.message=Aufgrund von Zugriffen laufender Prozesse oder geöffneter Dateien konnte „%s“ nicht gesperrt werden. Du kannst das Sperren dieses Tresors erzwingen, allerdings kann dies zum Verlust ungespeicherter Daten führen.
|
||||
lock.forced.confirmBtn=Sperren erzwingen
|
||||
## Failure
|
||||
lock.fail.heading=Tresor konnte nicht gesperrt werden.
|
||||
lock.fail.message=Der Tresor „%s“ konnte nicht gesperrt werden. Stellen Sie sicher, dass Sie Ihre ungespeicherten Arbeit an anderer Stelle speichern und wichtige Lese-/Schreibvorgänge abgeschlossen sind. Um den Tresor zu schließen, beenden Sie den Cryptomator-Prozess.
|
||||
|
||||
# Migration
|
||||
migration.title=Tresor aktualisieren
|
||||
## Start
|
||||
@@ -140,6 +149,8 @@ preferences.general.theme.automatic=Automatisch
|
||||
preferences.general.theme.light=Hell
|
||||
preferences.general.theme.dark=Dunkel
|
||||
preferences.general.unlockThemes=Dunklen Modus freischalten
|
||||
preferences.general.showMinimizeButton=Minimieren-Schaltfläche anzeigen
|
||||
preferences.general.showTrayIcon=Symbol im Infobereich anzeigen (Neustart erforderlich)
|
||||
preferences.general.startHidden=Cryptomator im Hintergrund starten
|
||||
preferences.general.debugLogging=Diagnoseprotokoll aktivieren
|
||||
preferences.general.debugDirectory=Protokolldateien anzeigen
|
||||
|
||||
@@ -102,10 +102,20 @@ unlock.success.message="%s" ξεκλειδώθηκε επιτυχώς! Το vaul
|
||||
unlock.success.rememberChoice=Απομνημόνευση επιλογής, μην ρωτήσεις ξανά
|
||||
unlock.success.revealBtn=Αποκάλυψη Vault
|
||||
## Failure
|
||||
unlock.error.heading=Αδυναμία ξεκλειδώματος vault
|
||||
### Invalid Mount Point
|
||||
unlock.error.invalidMountPoint.notExisting=Το σημείο προσάρτησης δεν είναι κενός φάκελος ή δεν υπάρχει: %s
|
||||
unlock.error.invalidMountPoint.existing=Το σημείο/φάκελος προσάρτησης υπάρχει ήδη ή ο γονικός φάκελος λείπει: %s
|
||||
|
||||
# Lock
|
||||
## Force
|
||||
lock.forced.heading=Το κανονικό κλείδωμα απέτυχε
|
||||
lock.forced.message=Το κλείδωμα "%s" μπλοκαρίστηκε από εκκρεμείς διεργασίες ή ανοιχτά αρχεία. Μπορείτε να εξαναγκάσετε το κλείδωμα του vault, αλλά η διακοπή Ι/Ο ενδέχεται να οδηγήσει σε απώλεια μη αποθηκευμένων δεδομένων.
|
||||
lock.forced.confirmBtn=Εξαναγκασμένο κλείδωμα
|
||||
## Failure
|
||||
lock.fail.heading=Το κλείδωμα του vault απέτυχε.
|
||||
lock.fail.message=Το Vault "%s" δεν κλειδώθηκε. Εξασφαλίστε την αποθήκευση της εργασίας σε άλλο σημείο και πως οι σημαντικές διεργασίας Ανάγνωσης/Εγγραφής έχουν ολοκληρωθεί. Για να κλείσετε το vault, τερματίστε τη διεργασία του Cryptomator.
|
||||
|
||||
# Migration
|
||||
migration.title=Αναβάθμιση Vault
|
||||
## Start
|
||||
|
||||
@@ -107,6 +107,15 @@ unlock.error.heading=No se puede desbloquear la bóveda
|
||||
unlock.error.invalidMountPoint.notExisting=El punto de montaje no es un directorio vacío o no existe: %s
|
||||
unlock.error.invalidMountPoint.existing=El punto de montaje/carpeta ya existe o falta la carpeta padre: %s
|
||||
|
||||
# Lock
|
||||
## Force
|
||||
lock.forced.heading=Bloqueo automático fallido
|
||||
lock.forced.message=El bloqueo de "%s" fue bloqueado por operaciones pendientes o archivos abiertos. Puede forzar el bloqueo de esta bóveda, sin embargo, interrumpir la I/O puede provocar la pérdida de datos no guardados.
|
||||
lock.forced.confirmBtn=Forzar bloqueo
|
||||
## Failure
|
||||
lock.fail.heading=Falló al bloquear la bóveda.
|
||||
lock.fail.message=No se pudo bloquear la bóveda "%s". Asegúrese de que el trabajo no guardado se ha guardado en otro lugar y las operaciones de lectura/escritura importantes han finalizado. Para cerrar la bóveda termine el proceso de Cryptomator.
|
||||
|
||||
# Migration
|
||||
migration.title=Mejorar bóveda
|
||||
## Start
|
||||
@@ -140,6 +149,8 @@ preferences.general.theme.automatic=Automático
|
||||
preferences.general.theme.light=Claro
|
||||
preferences.general.theme.dark=Oscuro
|
||||
preferences.general.unlockThemes=Desbloquear el modo oscuro
|
||||
preferences.general.showMinimizeButton=Mostrar botón minimizar
|
||||
preferences.general.showTrayIcon=Mostrar icono de bandeja (requiere reiniciar)
|
||||
preferences.general.startHidden=Ocultar ventana al iniciar Cryptomator
|
||||
preferences.general.debugLogging=Habilitar registro de depuración
|
||||
preferences.general.debugDirectory=Revelar archivos de registro
|
||||
|
||||
@@ -107,6 +107,15 @@ unlock.error.heading=Impossible de déverrouiller le coffre
|
||||
unlock.error.invalidMountPoint.notExisting=Le point de montage «%s» n'est pas un répertoire, n'est pas vide ou n'existe pas.
|
||||
unlock.error.invalidMountPoint.existing=Le point de montage/le répertoire existe déjà ou le répertoire parent est manquant: %s
|
||||
|
||||
# Lock
|
||||
## Force
|
||||
lock.forced.heading=Le verrouillage normal a échoué
|
||||
lock.forced.message=Le verrouillage de «%s» a été bloqué par des opérations en attente ou des fichiers ouverts. Vous pouvez forcer le verrouillage de ce coffre, mais l'interruption d'E/S peut entraîner la perte de données non enregistrées.
|
||||
lock.forced.confirmBtn=Forcer le verrouillage
|
||||
## Failure
|
||||
lock.fail.heading=Le verrouillage du coffre a échoué.
|
||||
lock.fail.message=Le coffre-fort "%s" n'a pas pu être verrouillé. Assurez-vous que le travail non sauvegardé est sauvegardé ailleurs et que les opérations importantes de lecture/écriture sont bien terminées. Pour fermer le coffre-fort, tuez le processus Cryptomator.
|
||||
|
||||
# Migration
|
||||
migration.title=Mettre à jour le coffre
|
||||
## Start
|
||||
@@ -140,6 +149,8 @@ preferences.general.theme.automatic=Automatique
|
||||
preferences.general.theme.light=Clair
|
||||
preferences.general.theme.dark=Sombre
|
||||
preferences.general.unlockThemes=Débloquer le mode nuit
|
||||
preferences.general.showMinimizeButton=Afficher le bouton de réduction
|
||||
preferences.general.showTrayIcon=Afficher l'icône de la barre des tâches (redémarrage requis)
|
||||
preferences.general.startHidden=Démarrer Cryptomator en mode caché
|
||||
preferences.general.debugLogging=Activer les logs debug
|
||||
preferences.general.debugDirectory=Afficher le journal
|
||||
|
||||
@@ -17,9 +17,11 @@ generic.error.title=कोई अनपेक्षित त्रुटि ह
|
||||
generic.error.instruction=ऐसा नहीं होना चाहिए था। कृपया नीचे त्रुटि पाठ की रिपोर्ट करें और इस त्रुटि के लिए क्या कदम उठाए, इसका विवरण शामिल करें।
|
||||
|
||||
# Defaults
|
||||
defaults.vault.vaultName=गुप्त तिजोरी
|
||||
|
||||
# Tray Menu
|
||||
traymenu.showMainWindow=दिखाएँ
|
||||
traymenu.showPreferencesWindow=प्राथमिकताएं
|
||||
traymenu.lockAllVaults=सभी को लॉक करें
|
||||
traymenu.quitApplication=बाहर निकलें
|
||||
traymenu.vault.unlock=अनलॉक करें
|
||||
@@ -42,9 +44,21 @@ addvaultwizard.new.locationPrompt=…
|
||||
addvaultwizard.new.directoryPickerLabel=अपने पसंद की जगह डालें
|
||||
addvaultwizard.new.directoryPickerButton=चुनें…
|
||||
addvaultwizard.new.directoryPickerTitle=निर्देशिका चुनें
|
||||
addvaultwizard.new.fileAlreadyExists=तिजोरी इस रास्ते पर नहीं बनाई जा सकती क्योंकि कुछ वस्तु पहले से मौजूद है।
|
||||
addvaultwizard.new.locationDoesNotExist=तिजोरी इस रास्ते पर नहीं बनाई जा सकती क्योंकि कम से कम एक पथ घटक मौजूद नहीं है।
|
||||
addvaultwizard.new.invalidName=अमान्य वॉल्ट नाम। कृपया एक नियमित निर्देशिका नाम पर विचार करें।
|
||||
### Password
|
||||
addvaultwizard.new.createVaultBtn=वॉल्ट बनाएं
|
||||
addvaultwizard.new.generateRecoveryKeyChoice=आप अपने पासवर्ड के बिना अपने डेटा तक नहीं पहुंच पाएंगे। क्या आप उस वक़्त के लिए एक पुनर्प्राप्ति कुंजी चाहते हैं जब आप अपना पासवर्ड खो देते हैं?
|
||||
addvaultwizard.new.generateRecoveryKeyChoice.yes=हाँ कृपया, पछतावा से बेहतर सुरक्षा
|
||||
addvaultwizard.new.generateRecoveryKeyChoice.no=नहीं धन्यवाद, मैं अपना पासवर्ड नहीं खोऊंगा
|
||||
### Information
|
||||
addvault.new.readme.storageLocation.fileName=IMPORTANT.rtf
|
||||
addvault.new.readme.storageLocation.1=⚠️ तिजोरी की फ़ाइलें ⚠️
|
||||
addvault.new.readme.storageLocation.2=यह आपकी तिजोरी का भंडारण स्थान है।
|
||||
addvault.new.readme.storageLocation.3=ऐसा न करें
|
||||
addvault.new.readme.storageLocation.4=• इस निर्देशिका के भीतर किसी भी फाइल को बदल दें या
|
||||
addvault.new.readme.storageLocation.5=• • इस डायरेक्टरी में एन्क्रिप्शन के लिए कोई भी फाइल पेस्ट करें।
|
||||
## Existing
|
||||
addvaultwizard.existing.chooseBtn=चुनें…
|
||||
## Success
|
||||
@@ -62,6 +76,10 @@ unlock.unlockBtn=अनलॉक करें
|
||||
## Failure
|
||||
### Invalid Mount Point
|
||||
|
||||
# Lock
|
||||
## Force
|
||||
## Failure
|
||||
|
||||
# Migration
|
||||
migration.title=वाउल्ट को अपग्रेड करें
|
||||
## Start
|
||||
@@ -71,6 +89,7 @@ migration.title=वाउल्ट को अपग्रेड करें
|
||||
## Impossible
|
||||
|
||||
# Preferences
|
||||
preferences.title=प्राथमिकताएं
|
||||
## General
|
||||
preferences.general=सामान्य
|
||||
## Volume
|
||||
@@ -84,6 +103,7 @@ preferences.general=सामान्य
|
||||
|
||||
# Main Window
|
||||
main.closeBtn.tooltip=बंद करें
|
||||
main.preferencesBtn.tooltip=प्राथमिकताएं
|
||||
## Drag 'n' Drop
|
||||
## Vault List
|
||||
main.vaultlist.addVaultBtn=वाउल्ट डालें
|
||||
|
||||
@@ -29,6 +29,10 @@
|
||||
## Failure
|
||||
### Invalid Mount Point
|
||||
|
||||
# Lock
|
||||
## Force
|
||||
## Failure
|
||||
|
||||
# Migration
|
||||
## Start
|
||||
## Run
|
||||
|
||||
@@ -81,6 +81,10 @@ unlock.unlockBtn=Buka Gembok
|
||||
## Failure
|
||||
### Invalid Mount Point
|
||||
|
||||
# Lock
|
||||
## Force
|
||||
## Failure
|
||||
|
||||
# Migration
|
||||
## Start
|
||||
## Run
|
||||
|
||||
@@ -102,10 +102,20 @@ unlock.success.message=Sbloccato "%s" con successo! La tua cassaforte è ora acc
|
||||
unlock.success.rememberChoice=Ricorda la scelta, non mostrare ancora
|
||||
unlock.success.revealBtn=Rivela Cassaforte
|
||||
## Failure
|
||||
unlock.error.heading=Impossibile sbloccare la cassaforte
|
||||
### Invalid Mount Point
|
||||
unlock.error.invalidMountPoint.notExisting=Il punto di montaggio non è una directory vuota o non esiste: %s
|
||||
unlock.error.invalidMountPoint.existing=Il punto di Mount/cartella esiste già o la cartella superiore è mancante: %s
|
||||
|
||||
# Lock
|
||||
## Force
|
||||
lock.forced.heading=Blocco normale fallito
|
||||
lock.forced.message=Il bloccaggio di "%s" è stato impedito da operazioni in sospeso o da file aperti. È possibile forzare il blocco di questa cassaforte, tuttavia interrompere I/O potrebbe causare la perdita di dati non salvati.
|
||||
lock.forced.confirmBtn=Forza Blocco
|
||||
## Failure
|
||||
lock.fail.heading=Blocco cassaforte fallito.
|
||||
lock.fail.message=Impossibile bloccare la cassaforte "%s". Assicurati che il lavoro non salvato sia salvato ovunque e che le operazioni di Lettura/Scrittura importanti siano concluse. Per chiudere la cassaforte, termina il processo di Cryptomator.
|
||||
|
||||
# Migration
|
||||
migration.title=Aggiorna Cassaforte
|
||||
## Start
|
||||
@@ -139,6 +149,7 @@ preferences.general.theme.automatic=Automatico
|
||||
preferences.general.theme.light=Chiaro
|
||||
preferences.general.theme.dark=Scuro
|
||||
preferences.general.unlockThemes=Sblocca modalità scura
|
||||
preferences.general.showMinimizeButton=Mostra pulsante riduci a icona
|
||||
preferences.general.startHidden=Nascondi la finestra all'avvio di Cryptomator
|
||||
preferences.general.debugLogging=Abilita i registri di debug
|
||||
preferences.general.debugDirectory=Mostra file log
|
||||
@@ -171,8 +182,33 @@ preferences.donationKey.getDonationKey=Ottieni una chiave di donazione
|
||||
preferences.about=Informazioni
|
||||
|
||||
# Vault Statistics
|
||||
stats.title=Statistiche per %s
|
||||
## Read
|
||||
stats.read.throughput.idle=Lettura: inattivo
|
||||
stats.read.throughput.kibs=Lettura: %.2f kiB/s
|
||||
stats.read.throughput.mibs=Lettura: %.2f MiB/s
|
||||
stats.read.total.data.none=Dati letti: -
|
||||
stats.read.total.data.kib=Dati letti: %.1f kiB
|
||||
stats.read.total.data.mib=Dati letti: %.1f MiB
|
||||
stats.read.total.data.gib=Dati letti: %.1f GiB
|
||||
stats.decr.total.data.none=Dati decriptati: -
|
||||
stats.decr.total.data.kib=Dati decrittografati: %.1f kiB
|
||||
stats.decr.total.data.mib=Dati decriptati: %.1f MiB
|
||||
stats.decr.total.data.gib=Dati decrittografati: %.1f GiB
|
||||
stats.read.accessCount=Totale lettura: %d
|
||||
## Write
|
||||
stats.write.throughput.idle=Scrivi: inattivo
|
||||
stats.write.throughput.kibs=Scrittura: %.2f kiB/s
|
||||
stats.write.throughput.mibs=Scrittura: %.2f MiB/s
|
||||
stats.write.total.data.none=Dati letti: -
|
||||
stats.write.total.data.kib=Dati scritti: %.1f kiB
|
||||
stats.write.total.data.mib=Dati scritti: %.1f MiB
|
||||
stats.write.total.data.gib=Dati scritti: %.1f GiB
|
||||
stats.encr.total.data.none=Dati crittografati: -
|
||||
stats.encr.total.data.kib=Dati crittografati: %.1f kiB
|
||||
stats.encr.total.data.mib=Dati crittografati: %.1f MiB
|
||||
stats.encr.total.data.gib=Dati crittografati: %.1f GiB
|
||||
stats.write.accessCount=Totale scritture: %d
|
||||
|
||||
# Main Window
|
||||
main.closeBtn.tooltip=Chiudi
|
||||
@@ -202,9 +238,11 @@ main.vaultDetail.accessLocation=I contenuti della tua cassaforte sono accessibil
|
||||
main.vaultDetail.revealBtn=Visualizza disco
|
||||
main.vaultDetail.lockBtn=Blocca
|
||||
main.vaultDetail.bytesPerSecondRead=Lettura:
|
||||
main.vaultDetail.bytesPerSecondWritten=Scrittura:
|
||||
main.vaultDetail.throughput.idle=inattivo
|
||||
main.vaultDetail.throughput.kbps=%.1f kiB/s
|
||||
main.vaultDetail.throughput.mbps=%.1f MiB/s
|
||||
main.vaultDetail.stats=Statistiche Cassaforte
|
||||
### Missing
|
||||
main.vaultDetail.missing.info=Cryptomator non ha potuto trovare una cassaforte in questo percorso.
|
||||
main.vaultDetail.missing.recheck=Ricontrollare
|
||||
|
||||
@@ -106,6 +106,15 @@ unlock.error.heading=金庫の解錠に失敗
|
||||
### Invalid Mount Point
|
||||
unlock.error.invalidMountPoint.notExisting=マウントポイントが空のディレクトリか存在していません: %s
|
||||
|
||||
# Lock
|
||||
## Force
|
||||
lock.forced.heading=正常な施錠に失敗しました
|
||||
lock.forced.message=保留中の操作または、開かれたファイルによって、"%s" の施錠が中断されました。この金庫を強制的に施錠することはできますが、I/O を中断すると保存されていないデータを失う可能性があります。
|
||||
lock.forced.confirmBtn=強制施錠
|
||||
## Failure
|
||||
lock.fail.heading=金庫の施錠に失敗しました。
|
||||
lock.fail.message=金庫 "%s" を施錠できませんでした。保存されていないデータがほかの場所に保存され、重要な読み込み/書き込み操作が完了していることを確認してください。金庫を閉じるには、Cryptomator のプロセスを強制終了してください。
|
||||
|
||||
# Migration
|
||||
migration.title=金庫をアップグレード
|
||||
## Start
|
||||
@@ -139,6 +148,8 @@ preferences.general.theme.automatic=自動
|
||||
preferences.general.theme.light=ライト
|
||||
preferences.general.theme.dark=ダーク
|
||||
preferences.general.unlockThemes=ダークモードの解錠
|
||||
preferences.general.showMinimizeButton=最小化ボタンを表示
|
||||
preferences.general.showTrayIcon=トレイアイコンを表示 (再起動が必要)
|
||||
preferences.general.startHidden=Cryptomator を開始したときウィンドウを隠す
|
||||
preferences.general.debugLogging=ログを有効にする
|
||||
preferences.general.debugDirectory=ログ ファイルを表示
|
||||
|
||||
@@ -107,6 +107,15 @@ unlock.error.heading=Vault 잠금을 해제 할 수 없습니다.
|
||||
unlock.error.invalidMountPoint.notExisting=구성지점이 존재하지 않거나 빈 디렉터리가 아닙니다: %s
|
||||
unlock.error.invalidMountPoint.existing=구성지점/폴더가 이미 존재하거나 부모 폴더가 없습니다: %s
|
||||
|
||||
# Lock
|
||||
## Force
|
||||
lock.forced.heading=정상적인 잠금을 실패하였습니다.
|
||||
lock.forced.message=대기 중인 작동이나 파일이 열려있어 "%s"를 잠그는데 실패하였습니다. 이 Vault를 강제로 잠글 수 있으나, 입/출력의 중단은 저장되지 않은 데이터의 유실을 초래할 수 있습니다.
|
||||
lock.forced.confirmBtn=강제 잠금
|
||||
## Failure
|
||||
lock.fail.heading=Vault 잠금에 실패하였습니다.
|
||||
lock.fail.message="%s" Vault를 잠글 수 없습니다. 저장되지 않은 작업이 다른 곳에 저장된 것과 중요한 읽기/쓰기 동작이 완료되었는지 확인 하십시요. Vault를 닫기 위해, Cryptomator 프로세스를 강제로 종료 하십시요.
|
||||
|
||||
# Migration
|
||||
migration.title=Vault 업그레이드
|
||||
## Start
|
||||
|
||||
@@ -101,6 +101,10 @@ unlock.success.revealBtn=Atklāt glabātuvi
|
||||
## Failure
|
||||
### Invalid Mount Point
|
||||
|
||||
# Lock
|
||||
## Force
|
||||
## Failure
|
||||
|
||||
# Migration
|
||||
migration.title=Jaunināt glabātuvi
|
||||
## Start
|
||||
|
||||
@@ -102,7 +102,16 @@ unlock.success.message=Vellykket opplåsning av "%s"! Hvelvet ditt er nå tilgje
|
||||
unlock.success.rememberChoice=Husk valget - ikke vis dette igjen
|
||||
unlock.success.revealBtn=Gjør hvelvet synlig
|
||||
## Failure
|
||||
unlock.error.heading=Klarer ikke å låse opp hvelvet
|
||||
### Invalid Mount Point
|
||||
unlock.error.invalidMountPoint.notExisting=Monteringspunktet "%s" er enten ikke en mappe, ikke tom eller eksisterer ikke.
|
||||
unlock.error.invalidMountPoint.existing=Monteringspunktet "%s" finnes enten allerede eller at overordnet mappe mangler.
|
||||
|
||||
# Lock
|
||||
## Force
|
||||
lock.forced.confirmBtn=Tving låsing
|
||||
## Failure
|
||||
lock.fail.heading=Låsing av hvelvet mislyktes.
|
||||
|
||||
# Migration
|
||||
migration.title=Oppgrader hvelv
|
||||
@@ -141,6 +150,7 @@ preferences.general.startHidden=Skjul vinduet når du starter Cryptomator
|
||||
preferences.general.debugLogging=Aktiver loggføring av feilsøk
|
||||
preferences.general.debugDirectory=Vis loggfiler
|
||||
preferences.general.autoStart=Start Cryptomator ved systemstart
|
||||
preferences.general.keychainBackend=Lagre passord med
|
||||
preferences.general.interfaceOrientation=Grensesnittorientering
|
||||
preferences.general.interfaceOrientation.ltr=Fra venstre til høyre
|
||||
preferences.general.interfaceOrientation.rtl=Fra høyre til venstre
|
||||
@@ -164,8 +174,34 @@ preferences.donationKey.getDonationKey=Få en donasjonsnøkkel
|
||||
preferences.about=Om
|
||||
|
||||
# Vault Statistics
|
||||
stats.title=Statistikk for %s
|
||||
stats.cacheHitRate=Cache treffrate
|
||||
## Read
|
||||
stats.read.throughput.idle=Les: inaktiv
|
||||
stats.read.throughput.kibs=Lest: %.2f kiB/s
|
||||
stats.read.throughput.mibs=Lest: %.2f MiB/s
|
||||
stats.read.total.data.none=Data lest: -
|
||||
stats.read.total.data.kib=Data lest: %.1f kiB
|
||||
stats.read.total.data.mib=Data lest: %.1f MiB
|
||||
stats.read.total.data.gib=Data lest: %.1f GiB
|
||||
stats.decr.total.data.none=Data dekryptert: -
|
||||
stats.decr.total.data.kib=Data dekryptert: %.1f kiB
|
||||
stats.decr.total.data.mib=Data dekryptert: %.1f MiB
|
||||
stats.decr.total.data.gib=Data dekryptert: %.1f GiB
|
||||
stats.read.accessCount=Lesninger totalt: %d
|
||||
## Write
|
||||
stats.write.throughput.idle=Skrive: inaktiv
|
||||
stats.write.throughput.kibs=Skriver: %.2f kiB/s
|
||||
stats.write.throughput.mibs=Skriver: %.2f MiB/s
|
||||
stats.write.total.data.none=Data lest: -
|
||||
stats.write.total.data.kib=Data skrevet: %.1f kiB
|
||||
stats.write.total.data.mib=Data skrevet: %.1f MiB
|
||||
stats.write.total.data.gib=Data skrevet: %.1f GiB
|
||||
stats.encr.total.data.none=Data kryptert: -
|
||||
stats.encr.total.data.kib=Data kryptert: %.1f kiB
|
||||
stats.encr.total.data.mib=Data kryptert: %.1f MiB
|
||||
stats.encr.total.data.gib=Data kryptert: %.1f GiB
|
||||
stats.write.accessCount=Skrivninger totalt: %d
|
||||
|
||||
# Main Window
|
||||
main.closeBtn.tooltip=Lukk
|
||||
@@ -195,9 +231,11 @@ main.vaultDetail.accessLocation=Innholdet i hvelvet ditt er tilgjengelig her:
|
||||
main.vaultDetail.revealBtn=Gjør enheten synlig
|
||||
main.vaultDetail.lockBtn=Lås
|
||||
main.vaultDetail.bytesPerSecondRead=Lesehastighet:
|
||||
main.vaultDetail.bytesPerSecondWritten=Skriv:
|
||||
main.vaultDetail.throughput.idle=inaktiv
|
||||
main.vaultDetail.throughput.kbps=%.1f kiB/s
|
||||
main.vaultDetail.throughput.mbps=%.1f MiB/s
|
||||
main.vaultDetail.stats=Hvelvstatistikk
|
||||
### Missing
|
||||
main.vaultDetail.missing.info=Cryptomator kunne ikke finne et hvelv på denne søkestien.
|
||||
main.vaultDetail.missing.recheck=Kontroller igjen
|
||||
|
||||
@@ -45,6 +45,7 @@ addvaultwizard.new.directoryPickerLabel=Andere locatie
|
||||
addvaultwizard.new.directoryPickerButton=Kies…
|
||||
addvaultwizard.new.directoryPickerTitle=Selecteer map
|
||||
addvaultwizard.new.fileAlreadyExists=Er kan op deze locatie geen kluis aangemaakt worden, omdat er een bepaald object bestaat.
|
||||
addvaultwizard.new.locationDoesNotExist=Er kan geen kluis op dit pad aangemaakt worden omdat ten minste één onderdeel van het pad niet bestaat.
|
||||
addvaultwizard.new.invalidName=Ongeldige kluisnaam. Overweeg een standaard mapnaam.
|
||||
### Password
|
||||
addvaultwizard.new.createVaultBtn=Kluis aanmaken
|
||||
@@ -98,9 +99,22 @@ unlock.savePassword=Wachtwoord Opslaan
|
||||
unlock.unlockBtn=Ontgrendel
|
||||
## Success
|
||||
unlock.success.message="%s" is met succes ontgrendeld! Uw kluis is nu toegankelijk.
|
||||
unlock.success.rememberChoice=Keuze onthouden en dit niet opnieuw tonen
|
||||
unlock.success.revealBtn=Toon kluis
|
||||
## Failure
|
||||
unlock.error.heading=Kan kluis niet ontgrendelen
|
||||
### Invalid Mount Point
|
||||
unlock.error.invalidMountPoint.notExisting=Koppelpunt "%s" is geen map, is niet leeg of bestaat niet.
|
||||
unlock.error.invalidMountPoint.existing=Koppelpunt "%s" bestaat reeds of de bovenliggende map ontbreekt.
|
||||
|
||||
# Lock
|
||||
## Force
|
||||
lock.forced.heading=De kluis kon niet op een gecontroleerde manier vergrendeld worden
|
||||
lock.forced.message=Het vergrendelen van "%s" werd voorkomen door lopende processen of geopende bestanden. U kunt de vergrendeling op deze kluis forceren, maar dit kan leiden tot het verlies van niet-opgeslagen gegevens.
|
||||
lock.forced.confirmBtn=Forceer vergrendeling
|
||||
## Failure
|
||||
lock.fail.heading=Kluis kan niet vergrendeld worden.
|
||||
lock.fail.message=Kluis "%s" kan niet vergrendeld worden. Zorg ervoor dat u uw niet-opgeslagen werk ergens anders opslaat en belangrijke lees-/schrijfbewerkingen hebt voltooid. Om de kluis te sluiten, beëindigt u het Cryptomator-proces.
|
||||
|
||||
# Migration
|
||||
migration.title=Kluis upgraden
|
||||
@@ -110,6 +124,7 @@ migration.start.confirm=Ja, mijn kluis is volledig gesynchroniseerd
|
||||
## Run
|
||||
migration.run.enterPassword=Voer wachtwoord voor "%s" in
|
||||
migration.run.startMigrationBtn=Kluis migreren
|
||||
migration.run.progressHint=Dit kan enige tijd duren…
|
||||
## Sucess
|
||||
migration.success.nextStepsInstructions="%s" is succesvol gemigreerd.\nU kunt nu uw kluis ontgrendelen.
|
||||
migration.success.unlockNow=Nu Ontgrendelen
|
||||
@@ -118,17 +133,33 @@ migration.error.missingFileSystemCapabilities.title=Niet ondersteund bestandssys
|
||||
migration.error.missingFileSystemCapabilities.description=Migratie is niet gestart, omdat uw kluis zich op een niet-adequaat bestandssysteem bevindt.
|
||||
migration.error.missingFileSystemCapabilities.reason.LONG_FILENAMES=Het bestandssysteem ondersteunt geen lange bestandsnamen.
|
||||
migration.error.missingFileSystemCapabilities.reason.LONG_PATHS=Het bestandssysteem ondersteunt geen lange paden.
|
||||
migration.error.missingFileSystemCapabilities.reason.READ_ACCESS=Het bestandssysteem staat lezen niet toe.
|
||||
migration.error.missingFileSystemCapabilities.reason.WRITE_ACCESS=Het bestandssysteem staat schrijven niet toe.
|
||||
## Impossible
|
||||
migration.impossible.heading=Kluis kan niet gemigreerd worden
|
||||
migration.impossible.reason=De kluis kan niet automatisch gemigreerd worden omdat de opslaglocatie of het toegangspunt niet compatibel is.
|
||||
migration.impossible.moreInfo=De kluis is nog te openen met een oudere versie. Instructies voor het handmatig migreren van een kluis zijn te vinden op
|
||||
|
||||
# Preferences
|
||||
preferences.title=Voorkeuren
|
||||
## General
|
||||
preferences.general=Algemeen
|
||||
preferences.general.theme=Uiterlijk
|
||||
preferences.general.theme.automatic=Automatisch
|
||||
preferences.general.theme.light=Licht
|
||||
preferences.general.theme.dark=Donker
|
||||
preferences.general.unlockThemes=Ontgrendel donkere modus
|
||||
preferences.general.showMinimizeButton=Knop minimaliseren weergeven
|
||||
preferences.general.showTrayIcon=Pictogram weergeven in systeemvak (herstart vereist)
|
||||
preferences.general.startHidden=Verberg venster bij het opstarten van Cryptomator
|
||||
preferences.general.debugLogging=Debug logging aanzetten
|
||||
preferences.general.debugDirectory=Logboekbestanden bekijken
|
||||
preferences.general.autoStart=Start Cryptomator als het systeem opstart
|
||||
preferences.general.keychainBackend=Bewaar wachtwoorden met
|
||||
preferences.general.keychainBackend.org.cryptomator.linux.keychain.SecretServiceKeychainAccess=Gnome sleutelhanger
|
||||
preferences.general.keychainBackend.org.cryptomator.linux.keychain.KDEWalletKeychainAccess=KDE Wallet
|
||||
preferences.general.keychainBackend.org.cryptomator.macos.keychain.MacSystemKeychainAccess=macOS-sleutelhangertoegang
|
||||
preferences.general.keychainBackend.org.cryptomator.windows.keychain.WindowsProtectedKeychainAccess=Windows-gegevensbescherming
|
||||
preferences.general.interfaceOrientation=Interface oriëntatie
|
||||
preferences.general.interfaceOrientation.ltr=Links naar rechts
|
||||
preferences.general.interfaceOrientation.rtl=Rechts naar links
|
||||
@@ -152,38 +183,73 @@ preferences.donationKey.getDonationKey=Verkrijg een donatiesleutel
|
||||
preferences.about=Over
|
||||
|
||||
# Vault Statistics
|
||||
stats.title=Statistieken voor %s
|
||||
stats.cacheHitRate=Succespercentage van cache
|
||||
## Read
|
||||
stats.read.throughput.idle=Lezen: inactief
|
||||
stats.read.throughput.kibs=Lezen: %.2f kiB/s
|
||||
stats.read.throughput.mibs=Lezen: %.2f MiB/s
|
||||
stats.read.total.data.none=Gegevens gelezen: -
|
||||
stats.read.total.data.kib=Gegevens gelezen: %.1f kiB
|
||||
stats.read.total.data.mib=Gegevens gelezen: %.1f MiB
|
||||
stats.read.total.data.gib=Gegevens gelezen: %.1f GiB
|
||||
stats.decr.total.data.none=Gegevens ontsleuteld: -
|
||||
stats.decr.total.data.kib=Gegevens ontsleuteld: %.1f kiB
|
||||
stats.decr.total.data.mib=Gegevens ontsleuteld: %.1f MiB
|
||||
stats.decr.total.data.gib=Gegevens ontsleuteld: %.1f GiB
|
||||
stats.read.accessCount=Totaal gelezen: %d
|
||||
## Write
|
||||
stats.write.throughput.idle=Schrijven: inactief
|
||||
stats.write.throughput.kibs=Schrijven: %.2f kiB/s
|
||||
stats.write.throughput.mibs=Schrijven: %.2f MiB/s
|
||||
stats.write.total.data.none=Gegevens gelezen: -
|
||||
stats.write.total.data.kib=Gegevens geschreven: %.1f kiB
|
||||
stats.write.total.data.mib=Gegevens geschreven: %.1f MiB
|
||||
stats.write.total.data.gib=Gegevens geschreven: %.1f GiB
|
||||
stats.encr.total.data.none=Gegevens versleuteld: -
|
||||
stats.encr.total.data.kib=Gegevens versleuteld: %.1f kiB
|
||||
stats.encr.total.data.mib=Gegevens versleuteld: %.1f MiB
|
||||
stats.encr.total.data.gib=Gegevens versleuteld: %.1f GiB
|
||||
stats.write.accessCount=Totaal geschreven: %d
|
||||
|
||||
# Main Window
|
||||
main.closeBtn.tooltip=Sluiten
|
||||
main.minimizeBtn.tooltip=Minimaliseer
|
||||
main.preferencesBtn.tooltip=Voorkeuren
|
||||
main.debugModeEnabled.tooltip=Foutopsporingsmodus is ingeschakeld
|
||||
main.donationKeyMissing.tooltip=Overweeg alstublieft om een donatie te doen
|
||||
## Drag 'n' Drop
|
||||
main.dropZone.dropVault=Voeg deze kluis toe
|
||||
main.dropZone.unknownDragboardContent=Als u een kluis wilt toevoegen, sleep deze dan naar dit venster
|
||||
## Vault List
|
||||
main.vaultlist.emptyList.onboardingInstruction=Klik hier om een kluis toe te voegen
|
||||
main.vaultlist.contextMenu.remove=Verwijder Kluis…
|
||||
main.vaultlist.addVaultBtn=Kluis toevoegen
|
||||
## Vault Detail
|
||||
### Welcome
|
||||
main.vaultDetail.welcomeOnboarding=Bedankt dat u Cryptomator heeft gekozen om uw bestanden te beschermen. Voor assistentie verwijzen we u naar de starthandleidingen:
|
||||
### Locked
|
||||
main.vaultDetail.lockedStatus=VERGRENDELD
|
||||
main.vaultDetail.unlockBtn=Ontgrendelen…
|
||||
main.vaultDetail.unlockNowBtn=Nu Ontgrendelen
|
||||
main.vaultDetail.optionsBtn=Kluis-instellingen
|
||||
main.vaultDetail.passwordSavedInKeychain=Wachtwoord opgeslagen
|
||||
### Unlocked
|
||||
main.vaultDetail.unlockedStatus=ONTGRENDELD
|
||||
main.vaultDetail.accessLocation=De inhoud van uw kluis is hier toegankelijk:
|
||||
main.vaultDetail.revealBtn=Toon Schijf
|
||||
main.vaultDetail.lockBtn=Vergrendel
|
||||
main.vaultDetail.bytesPerSecondRead=Lezen:
|
||||
main.vaultDetail.bytesPerSecondWritten=Schrijven:
|
||||
main.vaultDetail.throughput.idle=inactief
|
||||
main.vaultDetail.throughput.kbps=%.1f kiB/s
|
||||
main.vaultDetail.throughput.mbps=%.1f MiB/s
|
||||
main.vaultDetail.stats=Kluisstatistieken
|
||||
### Missing
|
||||
main.vaultDetail.missing.info=Cryptomator kon op dit pad geen kluis vinden.
|
||||
main.vaultDetail.missing.recheck=Controleer nog eens
|
||||
main.vaultDetail.missing.remove=Verwijderen van kluislijst…
|
||||
main.vaultDetail.missing.changeLocation=Verander de locatie van de kluis…
|
||||
### Needs Migration
|
||||
main.vaultDetail.migrateButton=Kluis upgraden
|
||||
main.vaultDetail.migratePrompt=Uw kluis moet worden bijgewerkt naar een nieuw formaat, voordat u deze kunt openen
|
||||
@@ -203,7 +269,10 @@ wrongFileAlert.link=Voor verdere ondersteuning, bezoek
|
||||
vaultOptions.general=Algemeen
|
||||
vaultOptions.general.vaultName=Kluisnaam
|
||||
vaultOptions.general.unlockAfterStartup=Ontgrendel kluis bij het starten van Cryptomator
|
||||
vaultOptions.general.actionAfterUnlock=Na een succesvolle ontgrendeling
|
||||
vaultOptions.general.actionAfterUnlock.ignore=Niets doen
|
||||
vaultOptions.general.actionAfterUnlock.reveal=Toon Schijf
|
||||
vaultOptions.general.actionAfterUnlock.ask=Vragen
|
||||
## Mount
|
||||
vaultOptions.mount=Aankoppelen
|
||||
vaultOptions.mount.readonly=Alleen-Lezen
|
||||
@@ -218,6 +287,7 @@ vaultOptions.mount.mountPoint.directoryPickerTitle=Kies een lege map
|
||||
## Master Key
|
||||
vaultOptions.masterkey=Wachtwoord
|
||||
vaultOptions.masterkey.changePasswordBtn=Wijzig wachtwoord
|
||||
vaultOptions.masterkey.forgetSavedPasswordBtn=Opgeslagen wachtwoord vergeten
|
||||
vaultOptions.masterkey.recoveryKeyExpanation=Een herstelsleutel is je enige manier om de toegang tot een kluis te herstellen als je je wachtwoord kwijtraakt.
|
||||
vaultOptions.masterkey.showRecoveryKeyBtn=Toon herstelsleutel
|
||||
vaultOptions.masterkey.recoverPasswordBtn=Wachtwoord herstellen
|
||||
|
||||
@@ -103,6 +103,10 @@ unlock.success.revealBtn=Gjer kvelven synleg
|
||||
## Failure
|
||||
### Invalid Mount Point
|
||||
|
||||
# Lock
|
||||
## Force
|
||||
## Failure
|
||||
|
||||
# Migration
|
||||
migration.title=Oppgrader kvelv
|
||||
## Start
|
||||
|
||||
@@ -107,6 +107,15 @@ unlock.error.heading=ਵਾਲਟ ਅਣ-ਲਾਕ ਕਰਨ ਲਈ ਅਸਮਰ
|
||||
unlock.error.invalidMountPoint.notExisting="%s" ਮਾਊਂਟ ਪੁਆਇੰਟ ਡਾਇਰੈਕਟਰੀ ਨਹੀਂ, ਖਾਲੀ ਨਹੀਂ ਜਾਂ ਮੌਜੂਦ ਹੀ ਨਹੀਂ ਹੈ।
|
||||
unlock.error.invalidMountPoint.existing="%s" ਮਾਊਂਟ ਪੁਆਇੰਟ ਪਹਿਲਾਂ ਹੀ ਮੌਜੂਦ ਹੈ ਜਾਂ ਉਸ ਦਾ ਮੂਲ ਫੋਲਡਰ ਗੁੰਮ ਹੈ।
|
||||
|
||||
# Lock
|
||||
## Force
|
||||
lock.forced.heading=ਸਧਾਰਨ ਲਾਕ ਕਰਨਾ ਅਸਫ਼ਲ ਹੈ
|
||||
lock.forced.message=ਬਾਕੀ ਰਹਿੰਦੀਆਂ ਕਾਰਵਾਈਆਂ ਜਾਂ ਫ਼ਾਈਲਾਂ ਖੁੱਲ੍ਹਣ ਕਰਕੇ "%s" ਲਾਕ ਕਰਨ ਨੂੰ ਰੋਕਿਆ ਗਿਆ ਹੈ। ਤੁਸੀਂ ਇਸ ਵਾਲਟ ਨੂੰ ਧੱਕੇ ਨਾਲ ਲਾਕ ਕਰ ਸਕਦੇ ਹੋ, ਪਰ I/O ਵਿੱਚ ਰੁਕਾਵਟ ਪਾਉਣ ਨਾਲ ਨਾ-ਸੰਭਾਲਿਆ ਡਾਟਾ ਖਤਮ ਹੋ ਜਾ ਸਕਦਾ ਹੈ।
|
||||
lock.forced.confirmBtn=ਧੱਕੇ ਨਾਲ ਲਾਕ ਕਰੋ
|
||||
## Failure
|
||||
lock.fail.heading=ਵਾਲਟ ਲਾਕ ਕਰਨਾ ਅਸਫ਼ਲ ਹੈ।
|
||||
lock.fail.message=ਵਾਲਟ "%s" ਨੂੰ ਲਾਕ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ। ਯਕੀਨੀ ਬਣਾਓ ਕਿ ਨਾ-ਸੰਭਾਲੇ ਕੰਮ ਨੂੰ ਹੋਰ ਥਾਂ ਸੰਭਾਲ ਲਿਆ ਹੈ ਅਤੇ ਖਾਸ ਪੜ੍ਹਨ/ਲਿਖਣ ਕਾਰਵਾਈਆਂ ਪੂਰੀਆਂ ਹੋਈਆਂ ਹਨ। ਵਾਲਟ ਨੂੰ ਬੰਦ ਕਰਨ ਲਈ Cryptomator ਕਾਰਵਾਈ ਨੂੰ ਖਤਮ ਕਰੋ।
|
||||
|
||||
# Migration
|
||||
migration.title=ਵਾਲਟ ਅੱਪਗਰੇਡ ਕਰੋ
|
||||
## Start
|
||||
|
||||
@@ -107,6 +107,15 @@ unlock.error.heading=Nie można odblokować sejfu
|
||||
unlock.error.invalidMountPoint.notExisting=Punkt montowania nie jest pustym katalogiem lub nie istnieje: %s
|
||||
unlock.error.invalidMountPoint.existing=Punkt montowania już istnieje lub brakuje katalogu nadrzędnego: %s
|
||||
|
||||
# Lock
|
||||
## Force
|
||||
lock.forced.heading=Blokada nie powiodła się
|
||||
lock.forced.message=Zamknięcie "%s" zostało zablokowane przez oczekujące operacje lub otwarte pliki. Możesz wymusić zamknięcie tego sejfu, ale może to spowodować utratę niezapisanych danych.
|
||||
lock.forced.confirmBtn=Wymuś zablokowanie
|
||||
## Failure
|
||||
lock.fail.heading=Błąd blokowania sejfu.
|
||||
lock.fail.message=Nie można zablokować sejfu "%s". Zapisz wszelkie zmiany w bezpiecznym miejscu i upewnij się, że nie ma żadnych ważnych oczekujących operacji odczytu/zapisu. W celu zamknięcia sejfu ubij Cryptomator.
|
||||
|
||||
# Migration
|
||||
migration.title=Aktualizuj sejf
|
||||
## Start
|
||||
@@ -140,10 +149,13 @@ preferences.general.theme.automatic=Automatycznie
|
||||
preferences.general.theme.light=Jasny
|
||||
preferences.general.theme.dark=Ciemny
|
||||
preferences.general.unlockThemes=Odblokuj tryb ciemny
|
||||
preferences.general.showMinimizeButton=Pokaż przycisk minimalizacji
|
||||
preferences.general.showTrayIcon=Pokaż ikonę zasobnika (wymaga ponownego uruchomienia)
|
||||
preferences.general.startHidden=Ukryj okno podczas uruchamiania programu Cryptomator
|
||||
preferences.general.debugLogging=Włącz logowanie w trybie debug
|
||||
preferences.general.debugDirectory=Pokaż pliki logowania
|
||||
preferences.general.autoStart=Uruchom Cryptomator po uruchomieniu systemu
|
||||
preferences.general.keychainBackend=Przechowuj hasła za pomocą
|
||||
preferences.general.keychainBackend.org.cryptomator.linux.keychain.SecretServiceKeychainAccess=Brelok kluczy Gnome
|
||||
preferences.general.keychainBackend.org.cryptomator.linux.keychain.KDEWalletKeychainAccess=Portfel KDE
|
||||
preferences.general.keychainBackend.org.cryptomator.macos.keychain.MacSystemKeychainAccess=Dostęp do pęku kluczy macOS
|
||||
@@ -171,6 +183,8 @@ preferences.donationKey.getDonationKey=Zdobądź klucz donacji
|
||||
preferences.about=O programie
|
||||
|
||||
# Vault Statistics
|
||||
stats.title=Statystyki dla %s
|
||||
stats.cacheHitRate=Trafność cache
|
||||
## Read
|
||||
stats.read.throughput.idle=Odczyt: bezczynny
|
||||
stats.read.throughput.kibs=Odczyt: %.2f kiB/s
|
||||
|
||||
@@ -95,6 +95,10 @@ unlock.success.revealBtn=Revelar Cofre
|
||||
## Failure
|
||||
### Invalid Mount Point
|
||||
|
||||
# Lock
|
||||
## Force
|
||||
## Failure
|
||||
|
||||
# Migration
|
||||
migration.title=Atualizar Cofre
|
||||
## Start
|
||||
|
||||
@@ -102,10 +102,20 @@ unlock.success.message="%s" foi desbloqueado com sucesso! Seu cofre agora está
|
||||
unlock.success.rememberChoice=Lembrar opção escolhida, não mostrar isto novamente
|
||||
unlock.success.revealBtn=Revelar Cofre
|
||||
## Failure
|
||||
unlock.error.heading=Não foi possível desbloquear o cofre
|
||||
### Invalid Mount Point
|
||||
unlock.error.invalidMountPoint.notExisting=O ponto de montagem não é um diretório vazio ou não existe: %s
|
||||
unlock.error.invalidMountPoint.existing=Ponto de montagem/pasta já existe ou a pasta pai está faltando: %s
|
||||
|
||||
# Lock
|
||||
## Force
|
||||
lock.forced.heading=Bloqueio normal falhou
|
||||
lock.forced.message=Trancar "%s" foi bloqueado por operações pendentes ou arquivos abertos. Você pode forçar o bloqueio deste cofre, no entanto, a interrupção pode resultar em perda de dados não salvos.
|
||||
lock.forced.confirmBtn=Forçar Bloqueio
|
||||
## Failure
|
||||
lock.fail.heading=O bloqueio do cofre falhou.
|
||||
lock.fail.message=Cofre "%s" não pôde ser bloqueado. Certifique-se de que o trabalho não salvo está salvo em outro lugar e que operações de Leitura/Escrita importantes sejam concluídas. Para fechar o cofre, encerre o processo do Cryptomator.
|
||||
|
||||
# Migration
|
||||
migration.title=Atualizar Cofre
|
||||
## Start
|
||||
@@ -139,13 +149,17 @@ preferences.general.theme.automatic=Automático
|
||||
preferences.general.theme.light=Claro
|
||||
preferences.general.theme.dark=Escuro
|
||||
preferences.general.unlockThemes=Desbloquear o modo escuro
|
||||
preferences.general.showMinimizeButton=Mostrar botão minimizar
|
||||
preferences.general.showTrayIcon=Mostrar ícone na barra do sistema (requer reinicialização)
|
||||
preferences.general.startHidden=Ocultar janela ao iniciar o Cryptomator
|
||||
preferences.general.debugLogging=Ativar log de debug
|
||||
preferences.general.debugDirectory=Mostrar arquivos de log
|
||||
preferences.general.autoStart=Iniciar o Cryptomator durante inicialização do sistema
|
||||
preferences.general.keychainBackend=Armazenar senhas no
|
||||
preferences.general.keychainBackend.org.cryptomator.linux.keychain.SecretServiceKeychainAccess=Keyring do Gnome
|
||||
preferences.general.keychainBackend.org.cryptomator.linux.keychain.KDEWalletKeychainAccess=Carteira KDE
|
||||
preferences.general.keychainBackend.org.cryptomator.macos.keychain.MacSystemKeychainAccess=Keychain Access do macOS
|
||||
preferences.general.keychainBackend.org.cryptomator.windows.keychain.WindowsProtectedKeychainAccess=Proteção de Dados do Windows
|
||||
preferences.general.interfaceOrientation=Orientação da interface
|
||||
preferences.general.interfaceOrientation.ltr=Da esquerda para a direita
|
||||
preferences.general.interfaceOrientation.rtl=Da direita para a esquerda
|
||||
@@ -169,8 +183,34 @@ preferences.donationKey.getDonationKey=Obtenha uma chave de doação
|
||||
preferences.about=Sobre
|
||||
|
||||
# Vault Statistics
|
||||
stats.title=Estatísticas para %s
|
||||
stats.cacheHitRate=Taxa de Utilização do Cache
|
||||
## Read
|
||||
stats.read.throughput.idle=Leitura: ociosa
|
||||
stats.read.throughput.kibs=Leitura: %.2f kiB/s
|
||||
stats.read.throughput.mibs=Leitura: %.2f MiB/s
|
||||
stats.read.total.data.none=Dados lidos: -
|
||||
stats.read.total.data.kib=Dados lidos: %.1f kiB
|
||||
stats.read.total.data.mib=Dados lidos: %.1f MiB
|
||||
stats.read.total.data.gib=Dados lidos: %.1f GiB
|
||||
stats.decr.total.data.none=Dados descriptografados: -
|
||||
stats.decr.total.data.kib=Dados descriptografados: %.1f kiB
|
||||
stats.decr.total.data.mib=Dados descriptografados: %.1f MiB
|
||||
stats.decr.total.data.gib=Dados descriptografados: %.1f GiB
|
||||
stats.read.accessCount=Total de leituras: %d
|
||||
## Write
|
||||
stats.write.throughput.idle=Escrita: ociosa
|
||||
stats.write.throughput.kibs=Escrita: %.2f kiB/s
|
||||
stats.write.throughput.mibs=Escrita: %.2f MiB/s
|
||||
stats.write.total.data.none=Dados lidos: -
|
||||
stats.write.total.data.kib=Dados gravados: %.1f kiB
|
||||
stats.write.total.data.mib=Dados gravados: %.1f MiB
|
||||
stats.write.total.data.gib=Dados gravados: %.1f GiB
|
||||
stats.encr.total.data.none=Dados criptografados: -
|
||||
stats.encr.total.data.kib=Dados criptografados: %.1f kiB
|
||||
stats.encr.total.data.mib=Dados criptografados: %.1f MiB
|
||||
stats.encr.total.data.gib=Dados criptografados: %.1f GiB
|
||||
stats.write.accessCount=Total gravado: %d
|
||||
|
||||
# Main Window
|
||||
main.closeBtn.tooltip=Fechar
|
||||
@@ -200,9 +240,11 @@ main.vaultDetail.accessLocation=O conteúdo do seu cofre está disponível aqui:
|
||||
main.vaultDetail.revealBtn=Revelar Volume
|
||||
main.vaultDetail.lockBtn=Bloquear
|
||||
main.vaultDetail.bytesPerSecondRead=Leitura:
|
||||
main.vaultDetail.bytesPerSecondWritten=Escrita:
|
||||
main.vaultDetail.throughput.idle=ocioso
|
||||
main.vaultDetail.throughput.kbps=%.1f kiB/s
|
||||
main.vaultDetail.throughput.mbps=%.1f MiB/s
|
||||
main.vaultDetail.stats=Estatísticas do Cofre
|
||||
### Missing
|
||||
main.vaultDetail.missing.info=O Cryptomator não conseguiu encontrar um cofre neste caminho.
|
||||
main.vaultDetail.missing.recheck=Verificar novamente
|
||||
|
||||
@@ -29,6 +29,10 @@
|
||||
## Failure
|
||||
### Invalid Mount Point
|
||||
|
||||
# Lock
|
||||
## Force
|
||||
## Failure
|
||||
|
||||
# Migration
|
||||
## Start
|
||||
## Run
|
||||
|
||||
@@ -38,7 +38,7 @@ addvaultwizard.welcome.existingButton=Открыть имеющееся хран
|
||||
addvaultwizard.new.nameInstruction=Выберите имя для хранилища
|
||||
addvaultwizard.new.namePrompt=Имя хранилища
|
||||
### Location
|
||||
addvaultwizard.new.locationInstruction=Где Cryptomator должен хранить зашифрованные файлы вашего хранилища?
|
||||
addvaultwizard.new.locationInstruction=Где Cryptomator должен хранить зашифрованные файлы хранилища?
|
||||
addvaultwizard.new.locationLabel=Место хранения
|
||||
addvaultwizard.new.locationPrompt=…
|
||||
addvaultwizard.new.directoryPickerLabel=Своё место
|
||||
@@ -51,13 +51,13 @@ addvaultwizard.new.invalidName=Неверное имя хранилища. Ук
|
||||
addvaultwizard.new.createVaultBtn=Создать хранилище
|
||||
addvaultwizard.new.generateRecoveryKeyChoice=Вы не сможете получить доступ к своим данным без пароля. Хотите создать ключ для восстановления на случай потери пароля?
|
||||
addvaultwizard.new.generateRecoveryKeyChoice.yes=Да, лучше предостеречься, чем потом жалеть
|
||||
addvaultwizard.new.generateRecoveryKeyChoice.no=Нет, спасибо, я не потеряю свой пароль
|
||||
addvaultwizard.new.generateRecoveryKeyChoice.no=Нет, спасибо, я не потеряю пароль
|
||||
### Information
|
||||
addvault.new.readme.storageLocation.fileName=ВАЖНО.rtf
|
||||
addvault.new.readme.storageLocation.1=⚠️ ФАЙЛЫ ХРАНИЛИЩА ⚠️
|
||||
addvault.new.readme.storageLocation.2=Это место, где находится ваше хранилище.
|
||||
addvault.new.readme.storageLocation.3=НЕТ
|
||||
addvault.new.readme.storageLocation.4=• изменяйте любые файлы в этой папке или
|
||||
addvault.new.readme.storageLocation.3=НЕЛЬЗЯ
|
||||
addvault.new.readme.storageLocation.4=• изменять любые файлы в этой папке или
|
||||
addvault.new.readme.storageLocation.5=• добавляйте в эту папку любые файлы для шифрования.
|
||||
addvault.new.readme.storageLocation.6=Чтобы зашифровать файлы и просмотреть содержимое хранилища, сделайте следующее:
|
||||
addvault.new.readme.storageLocation.7=1. Добавьте это хранилище в Cryptomator.
|
||||
@@ -102,11 +102,20 @@ unlock.success.message=Разблокировка "%s" успешно выпол
|
||||
unlock.success.rememberChoice=Запомнить выбор и больше не спрашивать
|
||||
unlock.success.revealBtn=Показать хранилище
|
||||
## Failure
|
||||
unlock.error.heading=Невозможно разблокировать хранилище
|
||||
unlock.error.heading=Не удалось разблокировать хранилище
|
||||
### Invalid Mount Point
|
||||
unlock.error.invalidMountPoint.notExisting=Точка монтирования %s - не папка, не пуста или не существует.
|
||||
unlock.error.invalidMountPoint.notExisting=Точка монтирования "%s" не является пустой папкой или не существует.
|
||||
unlock.error.invalidMountPoint.existing=Точка монтирования %s уже существует, либо отсутствует родительская папка.
|
||||
|
||||
# Lock
|
||||
## Force
|
||||
lock.forced.heading=Не удалось выполнить мягкую блокировку
|
||||
lock.forced.message=Блокировка "%s" невозможна из-за незавершённых операций или открытых файлов. Вы можете заблокировать это хранилище принудительно, однако прерывание ввода-вывода может привести к потере несохранённых данных.
|
||||
lock.forced.confirmBtn=Принудительная блокировка
|
||||
## Failure
|
||||
lock.fail.heading=Не удалось заблокировать хранилище.
|
||||
lock.fail.message=Хранилище "%s" не удалось заблокировать. Убедитесь, что несохранённые данные сохранены в другом месте и завершены важные операции чтения/записи. Чтобы закрыть хранилище, завершите процесс Cryptomator.
|
||||
|
||||
# Migration
|
||||
migration.title=Обновить хранилище
|
||||
## Start
|
||||
@@ -135,20 +144,23 @@ migration.impossible.moreInfo=Хранилище по-прежнему можн
|
||||
preferences.title=Настройки
|
||||
## General
|
||||
preferences.general=Общие
|
||||
preferences.general.theme=Тема
|
||||
preferences.general.theme=Оформление
|
||||
preferences.general.theme.automatic=Автоматически
|
||||
preferences.general.theme.light=Светлая
|
||||
preferences.general.theme.dark=Тёмная
|
||||
preferences.general.unlockThemes=Разблокировать тёмный режим
|
||||
preferences.general.showMinimizeButton=Показать кнопку сворачивания
|
||||
preferences.general.showTrayIcon=Показать значок в панели задач (требуется перезапуск)
|
||||
preferences.general.startHidden=Скрывать окно при запуске Cryptomator
|
||||
preferences.general.debugLogging=Вести журнал отладки
|
||||
preferences.general.debugDirectory=Показать файлы журнала
|
||||
preferences.general.autoStart=Запускать Cryptomator при старте системы
|
||||
preferences.general.keychainBackend=Хранить пароли в
|
||||
preferences.general.keychainBackend.org.cryptomator.linux.keychain.SecretServiceKeychainAccess=Связка ключей Gnome
|
||||
preferences.general.keychainBackend.org.cryptomator.linux.keychain.KDEWalletKeychainAccess=Бумажник KDE
|
||||
preferences.general.keychainBackend.org.cryptomator.linux.keychain.KDEWalletKeychainAccess=Хранилище ключей KDE
|
||||
preferences.general.keychainBackend.org.cryptomator.macos.keychain.MacSystemKeychainAccess=Доступ к связке ключей macOS
|
||||
preferences.general.keychainBackend.org.cryptomator.windows.keychain.WindowsProtectedKeychainAccess=Защита данных Windows
|
||||
preferences.general.interfaceOrientation=Ориентация интерфейса
|
||||
preferences.general.interfaceOrientation=Интерфейс
|
||||
preferences.general.interfaceOrientation.ltr=Слева направо
|
||||
preferences.general.interfaceOrientation.rtl=Справа налево
|
||||
## Volume
|
||||
@@ -165,7 +177,7 @@ preferences.updates.updateAvailable=Доступно обновление до
|
||||
## Donation Key
|
||||
preferences.donationKey=Пожертвование
|
||||
preferences.donationKey.registeredFor=Зарегистрировано: %s
|
||||
preferences.donationKey.noDonationKey=Не найден ключ пожертвования. Он напоминает лицензионный ключ, но для удивительных людей, использующих свободное ПО ;-)
|
||||
preferences.donationKey.noDonationKey=Не найден ключ пожертвования. Этот ключ похож на лицензионный, но для тех, кто использует бесплатное ПО. ;-)
|
||||
preferences.donationKey.getDonationKey=Получить ключ пожертвования
|
||||
## About
|
||||
preferences.about=О программе
|
||||
@@ -221,7 +233,7 @@ main.vaultDetail.lockedStatus=ЗАБЛОКИРОВАНО
|
||||
main.vaultDetail.unlockBtn=Разблокировка…
|
||||
main.vaultDetail.unlockNowBtn=Разблокировать
|
||||
main.vaultDetail.optionsBtn=Параметры хранилища
|
||||
main.vaultDetail.passwordSavedInKeychain=Пароль сохранен
|
||||
main.vaultDetail.passwordSavedInKeychain=Пароль сохранён
|
||||
### Unlocked
|
||||
main.vaultDetail.unlockedStatus=РАЗБЛОКИРОВАНО
|
||||
main.vaultDetail.accessLocation=Содержимое хранилища доступно здесь:
|
||||
@@ -247,7 +259,7 @@ wrongFileAlert.title=Как шифровать файлы
|
||||
wrongFileAlert.header.title=Вы пытались зашифровать эти файлы?
|
||||
wrongFileAlert.header.lead=Для этого Cryptomator создаёт том в системном диспетчере файлов.
|
||||
wrongFileAlert.instruction.0=Чтобы зашифровать файлы, выполните следующее:
|
||||
wrongFileAlert.instruction.1=1. Разблокируйте ваше хранилище.
|
||||
wrongFileAlert.instruction.1=1. Разблокируйте хранилище.
|
||||
wrongFileAlert.instruction.2=2. Нажмите кнопку "Показать", чтобы открыть том в диспетчере файлов.
|
||||
wrongFileAlert.instruction.3=3. Добавьте файлы в этот том.
|
||||
wrongFileAlert.link=Если нужна помощь, посетите
|
||||
@@ -267,7 +279,7 @@ vaultOptions.mount.readonly=Только чтение
|
||||
vaultOptions.mount.customMountFlags=Свои флаги монтирования
|
||||
vaultOptions.mount.winDriveLetterOccupied=занято
|
||||
vaultOptions.mount.mountPoint=Точка монтирования
|
||||
vaultOptions.mount.mountPoint.auto=Автоматически выбирать подходящую
|
||||
vaultOptions.mount.mountPoint.auto=Автоматически выбрать подходящее расположение
|
||||
vaultOptions.mount.mountPoint.driveLetter=Использовать назначенную букву диска
|
||||
vaultOptions.mount.mountPoint.custom=Свой путь
|
||||
vaultOptions.mount.mountPoint.directoryPickerButton=Выбрать…
|
||||
@@ -302,5 +314,5 @@ passwordStrength.messageLabel.3=Сильный
|
||||
passwordStrength.messageLabel.4=Очень сильный
|
||||
|
||||
# Quit
|
||||
quit.prompt=Выйти из приложения? Есть разблокированные хранилища.
|
||||
quit.prompt=Выйти из приложения? Есть незаблокированные хранилища.
|
||||
quit.lockAndQuit=Заблокировать и выйти
|
||||
|
||||
@@ -104,6 +104,15 @@ unlock.error.heading=Nie je možné odomknúť účet
|
||||
unlock.error.invalidMountPoint.notExisting=Bod pripojenia "%s" nie je adresár, nie je prázdny alebo neexistuje.
|
||||
unlock.error.invalidMountPoint.existing=Bod pripojenia "%s" už existuje alebo chýba nadradený adresár.
|
||||
|
||||
# Lock
|
||||
## Force
|
||||
lock.forced.heading=Bežné uzamknutie zlyhalo
|
||||
lock.forced.message=Zamknutie "%s" bolo zablokované prebiehajúcimi operáciami alebo otvorenými súbormi. Smiete vynútiť uzamknutie tejto peňaženky, ale prerušením I/O môže viesť k strate alebo neuloženiu dát.
|
||||
lock.forced.confirmBtn=Vynútené uzamknutie
|
||||
## Failure
|
||||
lock.fail.heading=Uzatváranie peňaženky zlyhalo.
|
||||
lock.fail.message=Peňaženku "%s" nie je možné uzamknúť. Uistite sa že neuložená páca je uložená inde a dôležité Read/Write operácie sú ukončené. Ináč uzavretím peňaženky, ukončíte proces Cryptomator-a.
|
||||
|
||||
# Migration
|
||||
## Start
|
||||
## Run
|
||||
|
||||
@@ -107,6 +107,10 @@ unlock.error.heading=Kan inte låsa upp valvet
|
||||
unlock.error.invalidMountPoint.notExisting=Monteringspunkten "%s" saknas eller är inte tom.
|
||||
unlock.error.invalidMountPoint.existing=Monteringspunkten "%s" finns redan eller så saknas överordnad mapp.
|
||||
|
||||
# Lock
|
||||
## Force
|
||||
## Failure
|
||||
|
||||
# Migration
|
||||
migration.title=Uppgradera valv
|
||||
## Start
|
||||
|
||||
@@ -102,10 +102,20 @@ unlock.success.message="%s" 'nin kilidi başarıyla açıldı! Kasanız şimdi e
|
||||
unlock.success.rememberChoice=Seçimi hatırla, bunu bir daha gösterme
|
||||
unlock.success.revealBtn=Kasayı Göster
|
||||
## Failure
|
||||
unlock.error.heading=Kasanın kilidi açılamıyor
|
||||
### Invalid Mount Point
|
||||
unlock.error.invalidMountPoint.notExisting=Bağlantı noktası boş bir dizin değil veya mevcut değil: %s
|
||||
unlock.error.invalidMountPoint.existing=Bağlama noktası / klasör zaten var veya ana klasör eksik: %s
|
||||
|
||||
# Lock
|
||||
## Force
|
||||
lock.forced.heading=Normal kilitleme başarısız oldu
|
||||
lock.forced.message="%s" nin kilitlenmesi, bekleyen işlemler veya açık dosyalar tarafından engellendi. Bu kasayı zorla kilitleyebilirsiniz, ancak G/Ç'nin kesilmesi kaydedilmemiş verilerin kaybına neden olabilir.
|
||||
lock.forced.confirmBtn=Kilitlemeyi Zorla
|
||||
## Failure
|
||||
lock.fail.heading=Kasa kilitlenemedi.
|
||||
lock.fail.message="%s" kasası kilitlenemedi. Kaydedilmemiş çalışmanın başka bir yere kaydedildiğinden ve önemli Okuma / Yazma işlemlerinin tamamlandığından emin olun. Kasayı kapatmak için Cryptomator işlemini sonlandırın.
|
||||
|
||||
# Migration
|
||||
migration.title=Kasayı Güncelle
|
||||
## Start
|
||||
@@ -139,13 +149,17 @@ preferences.general.theme.automatic=Otomatik
|
||||
preferences.general.theme.light=Açık
|
||||
preferences.general.theme.dark=Koyu
|
||||
preferences.general.unlockThemes=Koyu modun kilidini aç
|
||||
preferences.general.showMinimizeButton=Küçültme düğmesini göster
|
||||
preferences.general.showTrayIcon=Sistem tepsisi simgesini göster (Yeniden başlatma gerekir)
|
||||
preferences.general.startHidden=Cryptomator'ı başlatırken pencereyi gizle
|
||||
preferences.general.debugLogging=Hata ayıklama günlüğünü etkinleştir
|
||||
preferences.general.debugDirectory=Kayıt dosyalarını göster
|
||||
preferences.general.autoStart=Cryptomator'u sistem başlangıcında çalıştır
|
||||
preferences.general.keychainBackend=Şifreleri şununla depola:
|
||||
preferences.general.keychainBackend.org.cryptomator.linux.keychain.SecretServiceKeychainAccess=Gnome Keyring
|
||||
preferences.general.keychainBackend.org.cryptomator.linux.keychain.KDEWalletKeychainAccess=KDE Cüzdan
|
||||
preferences.general.keychainBackend.org.cryptomator.macos.keychain.MacSystemKeychainAccess=macOS Anahtar Zinciri Erişimi
|
||||
preferences.general.keychainBackend.org.cryptomator.windows.keychain.WindowsProtectedKeychainAccess=Windows Veri Koruması
|
||||
preferences.general.interfaceOrientation=Arayüz Yönü
|
||||
preferences.general.interfaceOrientation.ltr=Sola Yaslı
|
||||
preferences.general.interfaceOrientation.rtl=Sağa Yaslı
|
||||
@@ -169,8 +183,34 @@ preferences.donationKey.getDonationKey=Bir bağış anahtarı al
|
||||
preferences.about=Hakkında
|
||||
|
||||
# Vault Statistics
|
||||
stats.title=%s İçin İstatistikler
|
||||
stats.cacheHitRate=Önbellek Kullanım Oranı
|
||||
## Read
|
||||
stats.read.throughput.idle=Okuma: boşta
|
||||
stats.read.throughput.kibs=Okuma: %.2f kB/s
|
||||
stats.read.throughput.mibs=Okuma: %.2f MB/s
|
||||
stats.read.total.data.none=Okunan veri: -
|
||||
stats.read.total.data.kib=Okunan veri: %.1f kB
|
||||
stats.read.total.data.mib=Okunan veri: %.1f MB
|
||||
stats.read.total.data.gib=Okunan veri: %.1f GB
|
||||
stats.decr.total.data.none=Şifresi çözülen veri: -
|
||||
stats.decr.total.data.kib=Şifresi çözülen veri: %.1f kB
|
||||
stats.decr.total.data.mib=Şifresi çözülen veri: %.1f MB
|
||||
stats.decr.total.data.gib=Şifresi çözülen veri: %.1f GB
|
||||
stats.read.accessCount=Toplam okuma: %d
|
||||
## Write
|
||||
stats.write.throughput.idle=Yazma: boşta
|
||||
stats.write.throughput.kibs=Yazma: %.2f kB/s
|
||||
stats.write.throughput.mibs=Yazma: %.2f MB/s
|
||||
stats.write.total.data.none=Yazılan veri: -
|
||||
stats.write.total.data.kib=Yazılan veri: %.1f kB
|
||||
stats.write.total.data.mib=Yazılan veri: %.1f MB
|
||||
stats.write.total.data.gib=Yazılan veri: %.1f GB
|
||||
stats.encr.total.data.none=Şifrelenen veri: -
|
||||
stats.encr.total.data.kib=Şifrelenen veri: %.1f kB
|
||||
stats.encr.total.data.mib=Şifrelenen veri: %.1f MB
|
||||
stats.encr.total.data.gib=Şifrelenen veri: %.1f GB
|
||||
stats.write.accessCount=Toplam yazma: %d
|
||||
|
||||
# Main Window
|
||||
main.closeBtn.tooltip=Kapat
|
||||
@@ -200,9 +240,11 @@ main.vaultDetail.accessLocation=Kasa içeriğinize buradan erişilebilir:
|
||||
main.vaultDetail.revealBtn=Sürücüyü Göster
|
||||
main.vaultDetail.lockBtn=Kilitle
|
||||
main.vaultDetail.bytesPerSecondRead=Okuma:
|
||||
main.vaultDetail.bytesPerSecondWritten=Yazma:
|
||||
main.vaultDetail.throughput.idle=boşta
|
||||
main.vaultDetail.throughput.kbps=%.1f kiB/s
|
||||
main.vaultDetail.throughput.mbps=%.1f MiB/s
|
||||
main.vaultDetail.stats=Kasa İstatistikleri
|
||||
### Missing
|
||||
main.vaultDetail.missing.info=Şifreleyici bu dosya yolunda bir kasa bulamadı.
|
||||
main.vaultDetail.missing.recheck=Yeniden denetle
|
||||
|
||||
@@ -95,11 +95,11 @@ forgetPassword.confirmBtn=忘记密码
|
||||
# Unlock
|
||||
unlock.title=解锁保险库
|
||||
unlock.passwordPrompt=输入 "%s" 的密码
|
||||
unlock.savePassword=保存密码
|
||||
unlock.savePassword=记住密码
|
||||
unlock.unlockBtn=解锁
|
||||
## Success
|
||||
unlock.success.message=已成功解锁 "%s"! 您现在可以访问该保险库
|
||||
unlock.success.rememberChoice=记住该选择,不要再显示
|
||||
unlock.success.rememberChoice=记住选项且不再显示
|
||||
unlock.success.revealBtn=显示保险库
|
||||
## Failure
|
||||
unlock.error.heading=无法解锁保险库
|
||||
@@ -107,6 +107,15 @@ unlock.error.heading=无法解锁保险库
|
||||
unlock.error.invalidMountPoint.notExisting=挂载点 "%s" 不是目录、非空或不存在
|
||||
unlock.error.invalidMountPoint.existing=挂载点 "%s" 已存在或缺少父文件夹
|
||||
|
||||
# Lock
|
||||
## Force
|
||||
lock.forced.heading=常规锁定失败
|
||||
lock.forced.message=锁定 "%s" 被挂起的操作或使用中的文件中断。您可以强制锁定此保险库,不过请注意打断 I/O 可能导致未保存的数据丢失
|
||||
lock.forced.confirmBtn=强制锁定
|
||||
## Failure
|
||||
lock.fail.heading=锁定保险库失败
|
||||
lock.fail.message=保险库 "%s" 无法锁定。请确保在其他地方保存未保存的工作,以及重要的 "读/写" 操作已完成。为了顺利关闭保险库,请查杀 Cryptomator 进程
|
||||
|
||||
# Migration
|
||||
migration.title=升级保险库
|
||||
## Start
|
||||
@@ -140,6 +149,8 @@ preferences.general.theme.automatic=自动
|
||||
preferences.general.theme.light=亮色
|
||||
preferences.general.theme.dark=暗色
|
||||
preferences.general.unlockThemes=解锁暗黑模式
|
||||
preferences.general.showMinimizeButton=显示最小化按钮
|
||||
preferences.general.showTrayIcon=显示托盘图标 (需重启)
|
||||
preferences.general.startHidden=最小化启动 Cryptomator 到系统托盘
|
||||
preferences.general.debugLogging=启用调试日志
|
||||
preferences.general.debugDirectory=显示日志文件
|
||||
|
||||
@@ -102,10 +102,20 @@ unlock.success.message=成功解鎖 "%s"!您現在可以存取您的加密檔
|
||||
unlock.success.rememberChoice=記得這個決定,不要再顯示
|
||||
unlock.success.revealBtn=顯示加密檔案庫
|
||||
## Failure
|
||||
unlock.error.heading=無法解鎖加密檔案庫
|
||||
### Invalid Mount Point
|
||||
unlock.error.invalidMountPoint.notExisting=掛載點不是空目錄或是不存在:%s
|
||||
unlock.error.invalidMountPoint.existing=掛載點已經存在或上層資料夾不存在:%s
|
||||
|
||||
# Lock
|
||||
## Force
|
||||
lock.forced.heading=正常鎖定失敗
|
||||
lock.forced.message=仍有未完成的操作或開啟中的檔案以致無法鎖定 "%s"。您可以強制鎖定這個加密檔案庫,不過中斷讀寫可能會導致資料遺失或未被儲存。
|
||||
lock.forced.confirmBtn=強制鎖定
|
||||
## Failure
|
||||
lock.fail.heading=鎖定加密檔案庫失敗。
|
||||
lock.fail.message=加密檔案庫 "%s" 無法被鎖定。請確保未存檔的工作已儲存在別的地方以及重要的讀寫工作都已經完成。請強制結束 Cryptomator 以關閉加密檔案庫。
|
||||
|
||||
# Migration
|
||||
migration.title=升級加密檔案庫
|
||||
## Start
|
||||
@@ -139,12 +149,17 @@ preferences.general.theme.automatic=自動
|
||||
preferences.general.theme.light=亮色
|
||||
preferences.general.theme.dark=暗色
|
||||
preferences.general.unlockThemes=解鎖暗色模式
|
||||
preferences.general.showMinimizeButton=顯示最小化按鈕
|
||||
preferences.general.showTrayIcon=顯示系統工作列圖示 (需要重新啟動)
|
||||
preferences.general.startHidden=啟動 Cryptomator 時隱藏視窗
|
||||
preferences.general.debugLogging=啟用除錯日誌
|
||||
preferences.general.debugDirectory=顯示日誌檔
|
||||
preferences.general.autoStart=系統啟動時同時啟動 Cryptomator
|
||||
preferences.general.keychainBackend=儲存密碼使用
|
||||
preferences.general.keychainBackend.org.cryptomator.linux.keychain.SecretServiceKeychainAccess=Gnome 鑰匙圈
|
||||
preferences.general.keychainBackend.org.cryptomator.linux.keychain.KDEWalletKeychainAccess=KDE 錢包
|
||||
preferences.general.keychainBackend.org.cryptomator.macos.keychain.MacSystemKeychainAccess=macOS 鑰匙圈
|
||||
preferences.general.keychainBackend.org.cryptomator.windows.keychain.WindowsProtectedKeychainAccess=Windows 數據保護
|
||||
preferences.general.interfaceOrientation=界面排版方向
|
||||
preferences.general.interfaceOrientation.ltr=由左至右
|
||||
preferences.general.interfaceOrientation.rtl=由右至左
|
||||
@@ -168,8 +183,34 @@ preferences.donationKey.getDonationKey=取得贊助金鑰
|
||||
preferences.about=關於
|
||||
|
||||
# Vault Statistics
|
||||
stats.title=%s 統計數據
|
||||
stats.cacheHitRate=快取命中率
|
||||
## Read
|
||||
stats.read.throughput.idle=讀取:閒置
|
||||
stats.read.throughput.kibs=讀取:%.2f kiB/s
|
||||
stats.read.throughput.mibs=讀取:%.2f MiB/s
|
||||
stats.read.total.data.none=資料讀取:無
|
||||
stats.read.total.data.kib=資料讀取:%.1f kiB
|
||||
stats.read.total.data.mib=資料讀取:%.1f MiB
|
||||
stats.read.total.data.gib=資料讀取:%.1f GiB
|
||||
stats.decr.total.data.none=資料解密:無
|
||||
stats.decr.total.data.kib=資料解密:%.1f kiB
|
||||
stats.decr.total.data.mib=資料解密:%.1f MiB
|
||||
stats.decr.total.data.gib=資料解密:%.1f GiB
|
||||
stats.read.accessCount=總讀取:%d
|
||||
## Write
|
||||
stats.write.throughput.idle=寫入:閒置
|
||||
stats.write.throughput.kibs=寫入:%.2f kiB/s
|
||||
stats.write.throughput.mibs=寫入:%.2f MiB/s
|
||||
stats.write.total.data.none=資料讀取:無
|
||||
stats.write.total.data.kib=資料寫入:%.1f kiB
|
||||
stats.write.total.data.mib=資料寫入:%.1f MiB
|
||||
stats.write.total.data.gib=資料寫入:%.1f GiB
|
||||
stats.encr.total.data.none=資料加密:無
|
||||
stats.encr.total.data.kib=資料加密:%.1f kiB
|
||||
stats.encr.total.data.mib=資料加密:%.1f MiB
|
||||
stats.encr.total.data.gib=資料加密:%.1f GiB
|
||||
stats.write.accessCount=總寫入:%d
|
||||
|
||||
# Main Window
|
||||
main.closeBtn.tooltip=關閉
|
||||
@@ -199,9 +240,11 @@ main.vaultDetail.accessLocation=您可以從這裡取得您加密檔案庫的內
|
||||
main.vaultDetail.revealBtn=顯示磁碟
|
||||
main.vaultDetail.lockBtn=鎖定
|
||||
main.vaultDetail.bytesPerSecondRead=讀取:
|
||||
main.vaultDetail.bytesPerSecondWritten=寫入:
|
||||
main.vaultDetail.throughput.idle=閒置
|
||||
main.vaultDetail.throughput.kbps=%.1f kiB/s
|
||||
main.vaultDetail.throughput.mbps=%.1f MiB/s
|
||||
main.vaultDetail.stats=加密檔案庫統計數據
|
||||
### Missing
|
||||
main.vaultDetail.missing.info=Cryptomator 無法在指定位置找到加密檔案庫。
|
||||
main.vaultDetail.missing.recheck=重新檢查
|
||||
|
||||
@@ -11,7 +11,7 @@ GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
Cryptomator uses 46 third-party dependencies under the following licenses:
|
||||
Cryptomator uses 47 third-party dependencies under the following licenses:
|
||||
Apache License v2.0:
|
||||
- jffi (com.github.jnr:jffi:1.2.23 - http://github.com/jnr/jffi)
|
||||
- jnr-a64asm (com.github.jnr:jnr-a64asm:1.0.0 - http://nexus.sonatype.org/oss-repository-hosting.html/jnr-a64asm)
|
||||
@@ -28,19 +28,20 @@ Cryptomator uses 46 third-party dependencies under the following licenses:
|
||||
- Apache Commons CLI (commons-cli:commons-cli:1.4 - http://commons.apache.org/proper/commons-cli/)
|
||||
- Apache Commons IO (commons-io:commons-io:2.6 - http://commons.apache.org/proper/commons-io/)
|
||||
- javax.inject (javax.inject:javax.inject:1 - http://code.google.com/p/atinject/)
|
||||
- Java Native Access (net.java.dev.jna:jna:5.5.0 - https://github.com/java-native-access/jna)
|
||||
- Java Native Access (net.java.dev.jna:jna:5.6.0 - https://github.com/java-native-access/jna)
|
||||
- Java Native Access Platform (net.java.dev.jna:jna-platform:5.5.0 - https://github.com/java-native-access/jna)
|
||||
- Apache Commons Lang (org.apache.commons:commons-lang3:3.11 - https://commons.apache.org/proper/commons-lang/)
|
||||
- Apache HttpCore (org.apache.httpcomponents:httpcore:4.4.13 - http://hc.apache.org/httpcomponents-core-ga)
|
||||
- Jackrabbit WebDAV Library (org.apache.jackrabbit:jackrabbit-webdav:2.21.3 - http://jackrabbit.apache.org/jackrabbit-webdav/)
|
||||
- Jetty :: Http Utility (org.eclipse.jetty:jetty-http:9.4.33.v20201020 - https://eclipse.org/jetty/jetty-http)
|
||||
- Jetty :: IO Utility (org.eclipse.jetty:jetty-io:9.4.33.v20201020 - https://eclipse.org/jetty/jetty-io)
|
||||
- Jetty :: Security (org.eclipse.jetty:jetty-security:9.4.33.v20201020 - https://eclipse.org/jetty/jetty-security)
|
||||
- Jetty :: Server Core (org.eclipse.jetty:jetty-server:9.4.33.v20201020 - https://eclipse.org/jetty/jetty-server)
|
||||
- Jetty :: Servlet Handling (org.eclipse.jetty:jetty-servlet:9.4.33.v20201020 - https://eclipse.org/jetty/jetty-servlet)
|
||||
- Jetty :: Utilities (org.eclipse.jetty:jetty-util:9.4.33.v20201020 - https://eclipse.org/jetty/jetty-util)
|
||||
- Jetty :: Webapp Application Support (org.eclipse.jetty:jetty-webapp:9.4.33.v20201020 - https://eclipse.org/jetty/jetty-webapp)
|
||||
- Jetty :: XML utilities (org.eclipse.jetty:jetty-xml:9.4.33.v20201020 - https://eclipse.org/jetty/jetty-xml)
|
||||
- Jetty :: Http Utility (org.eclipse.jetty:jetty-http:9.4.35.v20201120 - https://eclipse.org/jetty/jetty-http)
|
||||
- Jetty :: IO Utility (org.eclipse.jetty:jetty-io:9.4.35.v20201120 - https://eclipse.org/jetty/jetty-io)
|
||||
- Jetty :: Security (org.eclipse.jetty:jetty-security:9.4.35.v20201120 - https://eclipse.org/jetty/jetty-security)
|
||||
- Jetty :: Server Core (org.eclipse.jetty:jetty-server:9.4.35.v20201120 - https://eclipse.org/jetty/jetty-server)
|
||||
- Jetty :: Servlet Handling (org.eclipse.jetty:jetty-servlet:9.4.35.v20201120 - https://eclipse.org/jetty/jetty-servlet)
|
||||
- Jetty :: Utilities (org.eclipse.jetty:jetty-util:9.4.35.v20201120 - https://eclipse.org/jetty/jetty-util)
|
||||
- Jetty :: Utilities :: Ajax(JSON) (org.eclipse.jetty:jetty-util-ajax:9.4.35.v20201120 - https://eclipse.org/jetty/jetty-util-ajax)
|
||||
- Jetty :: Webapp Application Support (org.eclipse.jetty:jetty-webapp:9.4.35.v20201120 - https://eclipse.org/jetty/jetty-webapp)
|
||||
- Jetty :: XML utilities (org.eclipse.jetty:jetty-xml:9.4.35.v20201120 - https://eclipse.org/jetty/jetty-xml)
|
||||
BSD:
|
||||
- asm (org.ow2.asm:asm:7.1 - http://asm.ow2.org/)
|
||||
- asm-analysis (org.ow2.asm:asm-analysis:7.1 - http://asm.ow2.org/)
|
||||
@@ -48,14 +49,15 @@ Cryptomator uses 46 third-party dependencies under the following licenses:
|
||||
- asm-tree (org.ow2.asm:asm-tree:7.1 - http://asm.ow2.org/)
|
||||
- asm-util (org.ow2.asm:asm-util:7.1 - http://asm.ow2.org/)
|
||||
Eclipse Public License - Version 1.0:
|
||||
- Jetty :: Http Utility (org.eclipse.jetty:jetty-http:9.4.33.v20201020 - https://eclipse.org/jetty/jetty-http)
|
||||
- Jetty :: IO Utility (org.eclipse.jetty:jetty-io:9.4.33.v20201020 - https://eclipse.org/jetty/jetty-io)
|
||||
- Jetty :: Security (org.eclipse.jetty:jetty-security:9.4.33.v20201020 - https://eclipse.org/jetty/jetty-security)
|
||||
- Jetty :: Server Core (org.eclipse.jetty:jetty-server:9.4.33.v20201020 - https://eclipse.org/jetty/jetty-server)
|
||||
- Jetty :: Servlet Handling (org.eclipse.jetty:jetty-servlet:9.4.33.v20201020 - https://eclipse.org/jetty/jetty-servlet)
|
||||
- Jetty :: Utilities (org.eclipse.jetty:jetty-util:9.4.33.v20201020 - https://eclipse.org/jetty/jetty-util)
|
||||
- Jetty :: Webapp Application Support (org.eclipse.jetty:jetty-webapp:9.4.33.v20201020 - https://eclipse.org/jetty/jetty-webapp)
|
||||
- Jetty :: XML utilities (org.eclipse.jetty:jetty-xml:9.4.33.v20201020 - https://eclipse.org/jetty/jetty-xml)
|
||||
- Jetty :: Http Utility (org.eclipse.jetty:jetty-http:9.4.35.v20201120 - https://eclipse.org/jetty/jetty-http)
|
||||
- Jetty :: IO Utility (org.eclipse.jetty:jetty-io:9.4.35.v20201120 - https://eclipse.org/jetty/jetty-io)
|
||||
- Jetty :: Security (org.eclipse.jetty:jetty-security:9.4.35.v20201120 - https://eclipse.org/jetty/jetty-security)
|
||||
- Jetty :: Server Core (org.eclipse.jetty:jetty-server:9.4.35.v20201120 - https://eclipse.org/jetty/jetty-server)
|
||||
- Jetty :: Servlet Handling (org.eclipse.jetty:jetty-servlet:9.4.35.v20201120 - https://eclipse.org/jetty/jetty-servlet)
|
||||
- Jetty :: Utilities (org.eclipse.jetty:jetty-util:9.4.35.v20201120 - https://eclipse.org/jetty/jetty-util)
|
||||
- Jetty :: Utilities :: Ajax(JSON) (org.eclipse.jetty:jetty-util-ajax:9.4.35.v20201120 - https://eclipse.org/jetty/jetty-util-ajax)
|
||||
- Jetty :: Webapp Application Support (org.eclipse.jetty:jetty-webapp:9.4.35.v20201120 - https://eclipse.org/jetty/jetty-webapp)
|
||||
- Jetty :: XML utilities (org.eclipse.jetty:jetty-xml:9.4.35.v20201120 - https://eclipse.org/jetty/jetty-xml)
|
||||
Eclipse Public License - v 2.0:
|
||||
- jnr-posix (com.github.jnr:jnr-posix:3.0.54 - http://nexus.sonatype.org/oss-repository-hosting.html/jnr-posix)
|
||||
GPLv2:
|
||||
@@ -68,7 +70,7 @@ Cryptomator uses 46 third-party dependencies under the following licenses:
|
||||
- javafx-graphics (org.openjfx:javafx-graphics:15 - https://openjdk.java.net/projects/openjfx/javafx-graphics/)
|
||||
LGPL 2.1:
|
||||
- jnr-posix (com.github.jnr:jnr-posix:3.0.54 - http://nexus.sonatype.org/oss-repository-hosting.html/jnr-posix)
|
||||
- Java Native Access (net.java.dev.jna:jna:5.5.0 - https://github.com/java-native-access/jna)
|
||||
- Java Native Access (net.java.dev.jna:jna:5.6.0 - https://github.com/java-native-access/jna)
|
||||
- Java Native Access Platform (net.java.dev.jna:jna-platform:5.5.0 - https://github.com/java-native-access/jna)
|
||||
MIT License:
|
||||
- java jwt (com.auth0:java-jwt:3.11.0 - https://github.com/auth0/java-jwt)
|
||||
|
||||
Reference in New Issue
Block a user