Compare commits

..
Author SHA1 Message Date
JaniruTEC 9601263645 Added an additional layer of abstraction to error reports
Fixed var names
Added abstract base class for controllers
Added base interface for error components
Added base interface for error component builders
Generified scene providers
Made GenericError classes and InvalidMountPointException classes depend on those base interfaces/classes
2021-04-11 02:54:21 +02:00
JaniruTEC 415cb78d87 Renamed errorComponent vars to genericErrorBuilder 2021-04-11 02:25:16 +02:00
JaniruTEC 4f43463649 Renamed files/constants used by the generic error report 2021-04-11 02:25:15 +02:00
JaniruTEC dc1f313082 Moved error report related files to new package 2021-04-11 01:55:35 +02:00
JaniruTEC 41d2a2c77e Added .idea/uiDesigner.xml to .gitignore 2021-04-10 23:16:00 +02:00
Armin Schrenk cf7cbae567 Set dev branch back to SNAPSHOT version
[ci skip]
2021-03-31 11:32:06 +02:00
Armin Schrenk 803f517c62 Merge tag '1.5.14' into develop
1.5.14
2021-03-31 11:11:34 +02:00
Armin Schrenk 0afa7b8e37 Merge branch 'release/1.5.14' 2021-03-31 11:11:27 +02:00
Armin Schrenk 1a0f70f8e8 updating third-party-licenses 2021-03-31 10:59:21 +02:00
Armin Schrenk 8737eb83f0 Bumping webdav-nio-adapter dependency 2021-03-31 10:58:23 +02:00
Armin Schrenk a96239a19f closes #1245 2021-03-31 10:52:30 +02:00
Armin Schrenk 2b7cfcd1dc preparing 1.5.14 2021-03-31 09:52:24 +02:00
Sebastian StenzelandGitHub ebccb61750 New Crowdin updates (#1560) 2021-03-31 09:46:45 +02:00
Armin Schrenk 285f2aec23 unify wording
[ci skip]
2021-03-30 16:10:24 +02:00
Armin SchrenkandGitHub 217e31fbd7 Merge pull request #1595 from cryptomator/feature/MCGA
Feature: Make Context menu Great Again
* adding additional entries
* fixes #1478
* only appears on a selected vault
2021-03-30 16:03:41 +02:00
Sebastian Stenzel f0ebf7a638 EasyBind rulez 2021-03-30 14:20:05 +02:00
Armin Schrenk c05c5e3f90 closes #961 2021-03-30 13:57:21 +02:00
Sebastian Stenzel 30f0c5e697 split VaultList and ContextMenu into two separate controllers 2021-03-30 13:43:37 +02:00
Armin Schrenk f989b8627c Update java-jwt 2021-03-30 13:10:54 +02:00
Armin Schrenk ff84230566 structure constructor 2021-03-30 11:53:30 +02:00
Armin Schrenk 3b4f6276b5 Improve selection model of list view:
* Clear selection if an empty space is clicked
* only open context menu if an item is selected
2021-03-30 11:25:22 +02:00
Armin Schrenk 2be7a050a4 refine wording
[ci skip]
2021-03-30 09:47:11 +02:00
Armin Schrenk 96a612127c add reveal entry to context menu. 2021-03-29 16:23:24 +02:00
Armin Schrenk 0bdfb7c9f9 Distinct between "unlock" and "unlock now" in context menu:
* inject keychainManager
* bind/unbind passphraseStored property to selected vault
* rename bindings to show possible action
* removed unused binding
* initialize properties properly
2021-03-29 12:59:48 +02:00
Armin Schrenk f556301249 fix suggestion 2021-03-29 12:47:46 +02:00
f77b237e59 simplify private function
Co-authored-by: Sebastian Stenzel <overheadhunter@users.noreply.github.com>
2021-03-29 12:44:57 +02:00
Armin Schrenk 61b7a39aad change level of a log message from warn to debug
[ci skip]
2021-03-29 10:53:48 +02:00
Tobias HagemannandGitHub 16bd84ee62 Update README.md
[ci skip]
2021-03-26 10:46:49 +01:00
Tobias HagemannandGitHub 3d0a97fcdf Update README.md
[ci skip]
2021-03-25 17:06:15 +01:00
Armin Schrenk 786d156b9f change wording in context menu entries 2021-03-23 15:08:23 +01:00
Armin Schrenk 9dc8b2cb47 Use Bindings instead of properties 2021-03-23 10:50:04 +01:00
Armin Schrenk 0e32e96c7d made context menu great again:
* added entry to unlock / lock a vault
* added entry to show vault options
2021-03-22 17:10:45 +01:00
Armin Schrenk 97afadd7b9 fixes #1478 2021-03-22 12:58:45 +01:00
Armin Schrenk b199b65e38 closes #176 2021-03-22 12:51:07 +01:00
Tobias HagemannandGitHub 999abf3c13 Update README.md
[ci skip]
2021-03-22 12:24:54 +01:00
Sebastian StenzelandGitHub 31e938de6a Merge pull request #1587 from cryptomator/feature/jdk-16
Update to JDK 16
2021-03-17 12:29:29 +01:00
Sebastian Stenzel 4c10ab764a updated README 2021-03-17 09:33:43 +01:00
Sebastian Stenzel 4e075ab0ca using pattern-matching instanceof where applicable 2021-03-17 09:22:16 +01:00
Sebastian Stenzel f73ae9759f use new Stream.toList() where applicable 2021-03-17 09:16:44 +01:00
Sebastian Stenzel f6283b2f7e using text blocks where applicable 2021-03-17 09:12:54 +01:00
Sebastian Stenzel b23d2e4def allow use of reflection in codacy coverage reporter 2021-03-17 08:19:58 +01:00
Sebastian Stenzel 91a2943599 update to JDK 16 2021-03-17 08:16:26 +01:00
Sebastian Stenzel e083fd0bcc skip certain steps on forks 2021-03-02 11:55:20 +01:00
ff687f1bae fix: main/pom.xml to reduce vulnerabilities (#1569)
The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-JAVA-ORGECLIPSEJETTY-1080611

Co-authored-by: snyk-bot <snyk-bot@snyk.io>
2021-03-02 08:43:10 +01:00
Sebastian Stenzel 84d2644f19 fix wrong versions that have been merged from main branch 2021-02-26 10:05:26 +01:00
Armin Schrenk f9a9d7b870 Merge tag '1.5.13' into develop
1.5.13
2021-02-24 16:21:07 +01:00
Armin Schrenk d75a8c4bba Merge branch 'release/1.5.13' 2021-02-24 16:21:06 +01:00
Armin Schrenk d326c7c990 preparing 1.5.13 2021-02-24 16:17:35 +01:00
Armin SchrenkandGitHub e8e63ca4fc Merge pull request #1517 from cryptomator/feature/translations
New Crowdin updates
2021-02-24 16:12:30 +01:00
Armin SchrenkandGitHub 6878f2e94b Merge pull request #1556 from cryptomator/feature/win-auto-theme
Feature/win auto theme
2021-02-24 14:31:17 +01:00
Armin Schrenk a17b416262 only remove system theme change listener, if one was previously registered. 2021-02-24 12:54:56 +01:00
Armin Schrenk fed572694f Merge branch 'develop' into feature/win-auto-theme
# Conflicts:
#	main/pom.xml
2021-02-24 12:25:04 +01:00
Armin Schrenk fe3d67d937 update build workflow 2021-02-24 12:21:13 +01:00
Armin Schrenk 3dcdeb1033 refactor pom to store targeted jdk build version in variable 2021-02-24 12:19:12 +01:00
Armin Schrenk 0898158c5a remove bintray as source repository in pom 2021-02-24 12:18:38 +01:00
Armin Schrenk 81091d4bdf bump integrations-* repos and implement new interface methods 2021-02-24 12:18:24 +01:00
Martin Beyer c9b1b1baa5 Fixes #1291 (Windows Automatic Theme) 2021-02-23 17:26:50 +01:00
Tobias Hagemann c81f3bd972 updated dependencies 2021-02-23 13:43:07 +01:00
Sebastian Stenzel 9f86b74320 New translations strings.properties (Greek)
[ci skip]
2021-02-23 09:32:09 +01:00
Sebastian Stenzel 2d8390a0f3 New translations strings.properties (Chinese Simplified)
[ci skip]
2021-02-22 11:47:50 +01:00
Sebastian Stenzel 8d3671175f New translations strings.properties (Swedish)
[ci skip]
2021-02-21 16:16:10 +01:00
Sebastian Stenzel 366011a222 New translations strings.properties (Swedish)
[ci skip]
2021-02-21 15:45:39 +01:00
Sebastian Stenzel c0c2e21055 New translations strings.properties (Korean)
[ci skip]
2021-02-20 02:29:34 +01:00
Sebastian Stenzel 63be96a151 New translations strings.properties (Korean)
[ci skip]
2021-02-20 01:58:05 +01:00
Sebastian Stenzel fc1df4bd99 New translations strings.properties (Catalan)
[ci skip]
2021-02-19 21:46:49 +01:00
Sebastian Stenzel 7657330931 New translations strings.properties (German)
[ci skip]
2021-02-19 13:17:33 +01:00
Sebastian Stenzel 4e44de3c3b New translations strings.properties (Portuguese, Brazilian)
[ci skip]
2021-02-19 01:07:24 +01:00
Sebastian Stenzel 8d902a72ca New translations strings.properties (Turkish)
[ci skip]
2021-02-18 19:39:40 +01:00
Sebastian Stenzel 7378031a72 New translations strings.properties (Spanish)
[ci skip]
2021-02-18 17:15:20 +01:00
Sebastian Stenzel f898c07c27 New translations strings.properties (German)
[ci skip]
2021-02-18 16:41:50 +01:00
Sebastian Stenzel c8f02d1045 New translations strings.properties (Czech)
[ci skip]
2021-02-18 14:56:07 +01:00
Sebastian Stenzel 4cc13b986b New translations strings.properties (Slovak)
[ci skip]
2021-02-18 14:22:12 +01:00
Sebastian Stenzel af7b6780f3 New translations strings.properties (Italian)
[ci skip]
2021-02-18 14:22:10 +01:00
Sebastian Stenzel 4a17d01004 New translations strings.properties (French)
[ci skip]
2021-02-18 13:42:57 +01:00
Sebastian Stenzel 1d68408e21 New translations strings.properties (Japanese)
[ci skip]
2021-02-18 13:42:49 +01:00
Sebastian Stenzel 821b1ee660 New translations strings.properties (Russian)
[ci skip]
2021-02-18 13:42:45 +01:00
Sebastian Stenzel c6616bd467 New translations strings.properties (Slovak)
[ci skip]
2021-02-18 13:42:44 +01:00
Sebastian Stenzel 4bb2589f16 New translations strings.properties (Polish)
[ci skip]
2021-02-18 13:42:37 +01:00
Sebastian Stenzel 896c3b3565 New translations strings.properties (Norwegian Bokmal)
[ci skip]
2021-02-18 13:09:32 +01:00
Sebastian Stenzel 6ee717a693 New translations strings.properties (French)
[ci skip]
2021-02-18 13:09:31 +01:00
Sebastian Stenzel 07ec858e1e New translations strings.properties (Spanish)
[ci skip]
2021-02-18 13:09:29 +01:00
Sebastian Stenzel a7c1e43ebc New translations strings.properties (Arabic)
[ci skip]
2021-02-18 13:09:28 +01:00
Sebastian Stenzel ac1cd3b073 New translations strings.properties (Catalan)
[ci skip]
2021-02-18 13:09:27 +01:00
Sebastian Stenzel 7474519faf New translations strings.properties (Czech)
[ci skip]
2021-02-18 13:09:26 +01:00
Sebastian Stenzel 340e474c33 New translations strings.properties (German)
[ci skip]
2021-02-18 13:09:24 +01:00
Sebastian Stenzel c90ab75427 New translations strings.properties (Greek)
[ci skip]
2021-02-18 13:09:23 +01:00
Sebastian Stenzel 848b3f77d3 New translations strings.properties (Hungarian)
[ci skip]
2021-02-18 13:09:21 +01:00
Sebastian Stenzel fb8cdb31ca New translations strings.properties (Italian)
[ci skip]
2021-02-18 13:09:20 +01:00
Sebastian Stenzel ba5f8053fb New translations strings.properties (Japanese)
[ci skip]
2021-02-18 13:09:19 +01:00
Sebastian Stenzel 38165becca New translations strings.properties (Korean)
[ci skip]
2021-02-18 13:09:17 +01:00
Sebastian Stenzel f731ac5c90 New translations strings.properties (Dutch)
[ci skip]
2021-02-18 13:09:16 +01:00
Sebastian Stenzel 0291702736 New translations strings.properties (Polish)
[ci skip]
2021-02-18 13:09:15 +01:00
Sebastian Stenzel ab63929861 New translations strings.properties (Portuguese)
[ci skip]
2021-02-18 13:09:12 +01:00
Sebastian Stenzel ca36fb8af3 New translations strings.properties (Slovak)
[ci skip]
2021-02-18 13:09:11 +01:00
Sebastian Stenzel 8cb29ff83b New translations strings.properties (Swedish)
[ci skip]
2021-02-18 13:09:10 +01:00
Sebastian Stenzel 304fa67dd7 New translations strings.properties (Turkish)
[ci skip]
2021-02-18 13:09:09 +01:00
Sebastian Stenzel a80ec32d2c New translations strings.properties (Chinese Simplified)
[ci skip]
2021-02-18 13:09:07 +01:00
Sebastian Stenzel dc4f21162e New translations strings.properties (Chinese Traditional)
[ci skip]
2021-02-18 13:09:06 +01:00
Sebastian Stenzel 3b8d7e0241 New translations strings.properties (Portuguese, Brazilian)
[ci skip]
2021-02-18 13:09:05 +01:00
Sebastian Stenzel 6891c68cf1 New translations strings.properties (Norwegian Nynorsk)
[ci skip]
2021-02-18 13:09:01 +01:00
Sebastian Stenzel 18b26fbc58 New translations strings.properties (Latvian)
[ci skip]
2021-02-18 13:09:00 +01:00
Sebastian Stenzel 1db8da6b6b New translations strings.properties (Bosnian)
[ci skip]
2021-02-18 13:08:57 +01:00
Sebastian Stenzel 14bce7e91d New translations strings.properties (Russian)
[ci skip]
2021-02-18 13:08:56 +01:00
Sebastian Stenzel 2674bc6f23 New translations strings.properties (Punjabi)
[ci skip]
2021-02-18 13:08:55 +01:00
Tobias HagemannandGitHub 74e1d6f991 Merge pull request #1545 from cryptomator/feature/save-password-clarification
"Save Password" Clarification
2021-02-18 13:07:04 +01:00
Tobias Hagemann 25dba028f8 added deep-linking to vault options tabs, changed "password saved" label to hyperlink 2021-02-18 11:32:14 +01:00
Tobias Hagemann bf51cc13d1 renamed "save password" to "remember password", switched placements of "vault options" hyperlink/button and "password saved" label 2021-02-18 09:15:19 +01:00
Sebastian Stenzel 24be36cccb New translations strings.properties (Spanish)
[ci skip]
2021-02-15 18:19:27 +01:00
Sebastian Stenzel 797e15c775 New translations strings.properties (Chinese Traditional)
[ci skip]
2021-02-15 17:08:04 +01:00
Sebastian Stenzel 2395dbcae9 New translations strings.properties (Italian)
[ci skip]
2021-02-15 16:09:11 +01:00
Sebastian Stenzel efacbbe2b6 New translations strings.properties (Bosnian)
[ci skip]
2021-02-15 15:40:45 +01:00
Sebastian Stenzel 2518086e46 New translations strings.properties (Polish)
[ci skip]
2021-02-15 15:40:44 +01:00
Sebastian Stenzel c733247611 New translations strings.properties (Japanese)
[ci skip]
2021-02-15 15:40:42 +01:00
Sebastian Stenzel 4f44e71e13 New translations strings.properties (Czech)
[ci skip]
2021-02-15 15:40:40 +01:00
Sebastian Stenzel 02aa46ece8 New translations strings.properties (Bosnian)
[ci skip]
2021-02-15 15:09:58 +01:00
Sebastian Stenzel 635f64c847 New translations strings.properties (German)
[ci skip]
2021-02-15 15:09:56 +01:00
Sebastian Stenzel 0a8516ae9a New translations strings.properties (French)
[ci skip]
2021-02-15 15:09:55 +01:00
Sebastian Stenzel c1edb30472 New translations strings.properties (Bosnian)
[ci skip]
2021-02-15 14:41:51 +01:00
Sebastian Stenzel 93c78b63ca New translations strings.properties (Russian)
[ci skip]
2021-02-15 14:41:50 +01:00
Sebastian Stenzel 3ccae93757 New translations strings.properties (Norwegian Bokmal)
[ci skip]
2021-02-15 14:09:30 +01:00
Sebastian Stenzel 450dec2baf New translations strings.properties (French)
[ci skip]
2021-02-15 14:09:29 +01:00
Sebastian Stenzel 36121527ca New translations strings.properties (Spanish)
[ci skip]
2021-02-15 14:09:27 +01:00
Sebastian Stenzel f30451f7e1 New translations strings.properties (Catalan)
[ci skip]
2021-02-15 14:09:25 +01:00
Sebastian Stenzel 74d7f63f64 New translations strings.properties (Czech)
[ci skip]
2021-02-15 14:09:24 +01:00
Sebastian Stenzel 350a4ab762 New translations strings.properties (German)
[ci skip]
2021-02-15 14:09:23 +01:00
Sebastian Stenzel 0e0e75b89c New translations strings.properties (Greek)
[ci skip]
2021-02-15 14:09:22 +01:00
Sebastian Stenzel e76440d928 New translations strings.properties (Hungarian)
[ci skip]
2021-02-15 14:09:20 +01:00
Sebastian Stenzel 0cbace67a5 New translations strings.properties (Italian)
[ci skip]
2021-02-15 14:09:19 +01:00
Sebastian Stenzel 84a3082589 New translations strings.properties (Japanese)
[ci skip]
2021-02-15 14:09:17 +01:00
Sebastian Stenzel cdfcca06d1 New translations strings.properties (Korean)
[ci skip]
2021-02-15 14:09:16 +01:00
Sebastian Stenzel 630bfa4cee New translations strings.properties (Dutch)
[ci skip]
2021-02-15 14:09:15 +01:00
Sebastian Stenzel 90cb7beb1f New translations strings.properties (Polish)
[ci skip]
2021-02-15 14:09:14 +01:00
Sebastian Stenzel d37fa33278 New translations strings.properties (Slovak)
[ci skip]
2021-02-15 14:09:11 +01:00
Sebastian Stenzel eed9c906cc New translations strings.properties (Swedish)
[ci skip]
2021-02-15 14:09:09 +01:00
Sebastian Stenzel 2b7ed5f4dd New translations strings.properties (Turkish)
[ci skip]
2021-02-15 14:09:08 +01:00
Sebastian Stenzel 6a7a309a2b New translations strings.properties (Chinese Simplified)
[ci skip]
2021-02-15 14:09:07 +01:00
Sebastian Stenzel 0382069995 New translations strings.properties (Chinese Traditional)
[ci skip]
2021-02-15 14:09:05 +01:00
Sebastian Stenzel 7c5f40d7d1 New translations strings.properties (Portuguese, Brazilian)
[ci skip]
2021-02-15 14:09:04 +01:00
Sebastian Stenzel 09e9530660 New translations strings.properties (Russian)
[ci skip]
2021-02-15 14:08:57 +01:00
Sebastian Stenzel 947d25b335 New translations strings.properties (Punjabi)
[ci skip]
2021-02-15 14:08:56 +01:00
Sebastian Stenzel 80cbc6699a fixed label
[ci skip]
2021-02-15 13:53:05 +01:00
Sebastian Stenzel da0933fa92 New translations strings.properties (Punjabi)
[ci skip]
2021-02-08 04:36:28 +01:00
Sebastian Stenzel adc9f32fb3 Merge branch 'master' into develop 2021-02-04 12:31:18 +01:00
Sebastian Stenzel 65369bdbff Merge branch 'release/1.5.12' 2021-02-04 12:27:42 +01:00
Sebastian Stenzel d18e618ef1 preparing 1.5.12 2021-02-04 12:27:02 +01:00
Armin Schrenk 970216dd59 Merge tag '1.5.12' into develop
1.5.12
2021-02-04 10:49:52 +01:00
Armin Schrenk 6840a649c7 Merge branch 'release/1.5.12' 2021-02-04 10:49:08 +01:00
Sebastian Stenzel e4709ed6fe Refactored FxmlFile and FxmlLoaderFactory 2021-02-01 12:06:38 +01:00
Sebastian Stenzel 01929c2288 New translations strings.properties (Hungarian)
[ci skip]
2021-01-22 13:48:57 +01:00
Sebastian Stenzel 2634433b2c New translations strings.properties (Hungarian)
[ci skip]
2021-01-22 13:19:41 +01:00
Sebastian Stenzel cb2bc17283 New translations strings.properties (Hungarian)
[ci skip]
2021-01-21 11:06:22 +01:00
107 changed files with 1339 additions and 659 deletions
+12 -6
View File
@@ -12,7 +12,7 @@ jobs:
- uses: actions/checkout@v2
- uses: actions/setup-java@v1
with:
java-version: 14
java-version: 16
- uses: actions/cache@v1
with:
path: ~/.m2/repository
@@ -25,12 +25,13 @@ jobs:
- name: Build and Test
run: mvn -B install --file main/pom.xml -Pcoverage
- name: Run Codacy Coverage Reporter
if: github.repository == 'cryptomator/cryptomator'
run: |
curl -o ~/codacy-coverage-reporter.jar https://repo.maven.apache.org/maven2/com/codacy/codacy-coverage-reporter/7.1.0/codacy-coverage-reporter-7.1.0-assembly.jar
$JAVA_HOME/bin/java -jar ~/codacy-coverage-reporter.jar report -l Java -r main/commons/target/site/jacoco/jacoco.xml --partial
$JAVA_HOME/bin/java -jar ~/codacy-coverage-reporter.jar report -l Java -r main/ui/target/site/jacoco/jacoco.xml --partial
$JAVA_HOME/bin/java -jar ~/codacy-coverage-reporter.jar report -l Java -r main/launcher/target/site/jacoco/jacoco.xml --partial
$JAVA_HOME/bin/java -jar ~/codacy-coverage-reporter.jar final
$JAVA_HOME/bin/java --illegal-access=permit -jar ~/codacy-coverage-reporter.jar report -l Java -r main/commons/target/site/jacoco/jacoco.xml --partial
$JAVA_HOME/bin/java --illegal-access=permit -jar ~/codacy-coverage-reporter.jar report -l Java -r main/ui/target/site/jacoco/jacoco.xml --partial
$JAVA_HOME/bin/java --illegal-access=permit -jar ~/codacy-coverage-reporter.jar report -l Java -r main/launcher/target/site/jacoco/jacoco.xml --partial
$JAVA_HOME/bin/java --illegal-access=permit -jar ~/codacy-coverage-reporter.jar final
env:
CODACY_PROJECT_TOKEN: ${{ secrets.CODACY_PROJECT_TOKEN }}
- name: Assemble buildkit-linux.zip
@@ -59,7 +60,7 @@ jobs:
name: Draft a Release on GitHub Releases
runs-on: ubuntu-latest
needs: build
if: startsWith(github.ref, 'refs/tags/')
if: startsWith(github.ref, 'refs/tags/') && github.repository == 'cryptomator/cryptomator'
steps:
- name: Download buildkit-linux.zip
uses: actions/download-artifact@v1
@@ -86,6 +87,11 @@ jobs:
release_name: ${{ github.ref }}
body: |
:construction: Work in Progress
TODO:
* [ ] add Linux appimage, zsync file and signature file
* [ ] add Windows installer and signature file
* [ ] add MacOs disk image and signature file
draft: true
prerelease: false
- name: Upload buildkit-linux.zip to GitHub Releases
+1
View File
@@ -21,5 +21,6 @@ pom.xml.versionsBackup
.idea/compiler.xml
.idea/encodings.xml
.idea/jarRepositories.xml
.idea/uiDesigner.xml
.idea/**/libraries/
*.iml
+1 -1
View File
@@ -8,7 +8,7 @@
</list>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_14" default="false" project-jdk-name="14" project-jdk-type="JavaSDK">
<component name="ProjectRootManager" version="2" languageLevel="JDK_16" project-jdk-name="16" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>
+19 -4
View File
@@ -2,7 +2,7 @@
[![Build](https://github.com/cryptomator/cryptomator/workflows/Build/badge.svg)](https://github.com/cryptomator/cryptomator/actions?query=workflow%3ABuild)
[![Known Vulnerabilities](https://snyk.io/test/github/cryptomator/cryptomator/badge.svg?targetFile=main%2Fpom.xml)](https://snyk.io/test/github/cryptomator/cryptomator?targetFile=main%2Fpom.xml)
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/2a0adf3cec6a4143b91035d3924178f1)](https://www.codacy.com/app/cryptomator/cryptomator?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=cryptomator/cryptomator&amp;utm_campaign=Badge_Grade)
[![Codacy Badge](https://app.codacy.com/project/badge/Grade/2a0adf3cec6a4143b91035d3924178f1)](https://www.codacy.com/gh/cryptomator/cryptomator/dashboard)
[![Twitter](https://img.shields.io/badge/twitter-@Cryptomator-blue.svg?style=flat)](http://twitter.com/Cryptomator)
[![Crowdin](https://badges.crowdin.net/cryptomator/localized.svg)](https://translate.cryptomator.org/)
[![Latest Release](https://img.shields.io/github/release/cryptomator/cryptomator.svg)](https://github.com/cryptomator/cryptomator/releases/latest)
@@ -17,11 +17,26 @@ Cryptomator is provided free of charge as an open-source project despite the hig
### Gold Sponsors
[<img src="https://cryptomator.org/img/sponsors/geewhiz.svg" alt="gee-whiz" height="96">](https://www.gee-whiz.de/)
<table>
<tbody>
<tr>
<td><a href="https://www.gee-whiz.de/"><img src="https://cryptomator.org/img/sponsors/geewhiz.svg" alt="gee-whiz" height="80"></a></td>
<td><a href="https://proxy-hub.com/"><img src="https://cryptomator.org/img/sponsors/proxyhub.svg" alt="Proxy-Hub" height="80"></a></td>
</tr>
</tbody>
</table>
### Silver Sponsors
[![TheBestVPN](https://cryptomator.org/img/sponsors/thebestvpn.png)](https://thebestvpn.com/)
<table>
<tbody>
<tr>
<td><a href="https://thebestvpn.com/"><img src="https://cryptomator.org/img/sponsors/thebestvpn@2x.png" alt="TheBestVPN" height="64"></a></td>
</tr>
</tbody>
</table>
- [Jameson Lopp](https://www.lopp.net/)
---
@@ -65,7 +80,7 @@ For more information on the security details visit [cryptomator.org](https://doc
### Dependencies
* JDK 14 (e.g. adoptopenjdk)
* JDK 16 (e.g. adoptopenjdk)
* Maven 3
* Optional: OS-dependent build tools for native packaging (see [Windows](https://github.com/cryptomator/cryptomator-win), [OS X](https://github.com/cryptomator/cryptomator-osx), [Linux](https://github.com/cryptomator/builder-containers))
@@ -47,10 +47,12 @@ public abstract class CommonsModule {
@Named("licensePublicKey")
static String provideLicensePublicKey() {
// in PEM format without the dash-escaped begin/end lines
return "MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQB7NfnqiZbg2KTmoflmZ71PbXru7oW" //
+ "fmnV2yv3eDjlDfGruBrqz9TtXBZV/eYWt31xu1osIqaT12lKBvZ511aaAkIBeOEV" //
+ "gwcBIlJr6kUw7NKzeJt7r2rrsOyQoOG2nWc/Of/NBqA3mIZRHk5Aq1YupFdD26QE" //
+ "r0DzRyj4ixPIt38CQB8=";
return """
MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQB7NfnqiZbg2KTmoflmZ71PbXru7oW\
fmnV2yv3eDjlDfGruBrqz9TtXBZV/eYWt31xu1osIqaT12lKBvZ511aaAkIBeOEV\
gwcBIlJr6kUw7NKzeJt7r2rrsOyQoOG2nWc/Of/NBqA3mIZRHk5Aq1YupFdD26QE\
r0DzRyj4ixPIt38CQB8=\
""";
}
@Provides
@@ -33,8 +33,8 @@ class LicenseChecker {
try {
byte[] keyBytes = BaseEncoding.base64().decode(pemEncodedPublicKey);
PublicKey key = KeyFactory.getInstance("EC").generatePublic(new X509EncodedKeySpec(keyBytes));
if (key instanceof ECPublicKey) {
return (ECPublicKey) key;
if (key instanceof ECPublicKey k) {
return k;
} else {
throw new IllegalStateException("Key not an EC public key.");
}
@@ -68,6 +68,11 @@ public class KeychainManager implements KeychainAccessProvider {
return keychain.getValue() != null;
}
@Override
public boolean isLocked() {
return keychain.getValue() == null || keychain.get().isLocked();
}
/**
* Checks if the keychain knows a passphrase for the given key.
* <p>
@@ -8,7 +8,7 @@ public enum UiTheme {
AUTOMATIC("preferences.general.theme.automatic");
public static UiTheme[] applicableValues() {
if (SystemUtils.IS_OS_MAC) {
if (SystemUtils.IS_OS_MAC || SystemUtils.IS_OS_WINDOWS) {
return values();
} else {
return new UiTheme[]{LIGHT, DARK};
@@ -173,8 +173,7 @@ public class VaultSettings {
@Override
public boolean equals(Object obj) {
if (obj instanceof VaultSettings && obj.getClass().equals(this.getClass())) {
VaultSettings other = (VaultSettings) obj;
if (obj instanceof VaultSettings other && obj.getClass().equals(this.getClass())) {
return Objects.equals(this.id, other.id);
} else {
return false;
@@ -45,7 +45,9 @@ public class FuseVolume extends AbstractVolume {
try {
Mounter mounter = FuseMountFactory.getMounter();
EnvironmentVariables envVars = EnvironmentVariables.create() //
.withFlags(splitFlags(mountFlags)).withMountPoint(mountPoint) //
.withFlags(splitFlags(mountFlags)) //
.withMountPoint(mountPoint) //
.withFileNameTranscoder(mounter.defaultFileNameTranscoder()) //
.build();
this.mount = mounter.mount(root, envVars);
} catch (CommandFailedException | FuseNotSupportedException e) {
@@ -355,8 +355,7 @@ public class Vault {
@Override
public boolean equals(Object obj) {
if (obj instanceof Vault && obj.getClass().equals(this.getClass())) {
final Vault other = (Vault) obj;
if (obj instanceof Vault other && obj.getClass().equals(this.getClass())) {
return Objects.equals(this.vaultSettings, other.vaultSettings);
} else {
return false;
@@ -22,10 +22,10 @@ class VaultListChangeListener implements ListChangeListener<Vault> {
public void onChanged(Change<? extends Vault> c) {
while (c.next()) {
if (c.wasAdded()) {
List<VaultSettings> addedSettings = c.getAddedSubList().stream().map(Vault::getVaultSettings).collect(Collectors.toList());
List<VaultSettings> addedSettings = c.getAddedSubList().stream().map(Vault::getVaultSettings).toList();
vaultSettingsList.addAll(c.getFrom(), addedSettings);
} else if (c.wasRemoved()) {
List<VaultSettings> removedSettings = c.getRemoved().stream().map(Vault::getVaultSettings).collect(Collectors.toList());
List<VaultSettings> removedSettings = c.getRemoved().stream().map(Vault::getVaultSettings).toList();
vaultSettingsList.removeAll(removedSettings);
}
}
@@ -79,7 +79,7 @@ public class VaultListManager {
}
private void addAll(Collection<VaultSettings> vaultSettings) {
Collection<Vault> vaults = vaultSettings.stream().map(this::create).collect(Collectors.toList());
Collection<Vault> vaults = vaultSettings.stream().map(this::create).toList();
vaultList.addAll(vaults);
}
@@ -32,7 +32,7 @@ class EnvironmentTest {
public void testSettingsPath() {
System.setProperty("cryptomator.settingsPath", "~/.config/Cryptomator/settings.json:~/.Cryptomator/settings.json");
List<Path> result = env.getSettingsPath().collect(Collectors.toList());
List<Path> result = env.getSettingsPath().toList();
MatcherAssert.assertThat(result, Matchers.hasSize(2));
MatcherAssert.assertThat(result, Matchers.contains(Paths.get("/home/testuser/.config/Cryptomator/settings.json"), //
Paths.get("/home/testuser/.Cryptomator/settings.json")));
@@ -43,7 +43,7 @@ class EnvironmentTest {
public void testIpcPortPath() {
System.setProperty("cryptomator.ipcPortPath", "~/.config/Cryptomator/ipcPort.bin:~/.Cryptomator/ipcPort.bin");
List<Path> result = env.getIpcPortPath().collect(Collectors.toList());
List<Path> result = env.getIpcPortPath().toList();
MatcherAssert.assertThat(result, Matchers.hasSize(2));
MatcherAssert.assertThat(result, Matchers.contains(Paths.get("/home/testuser/.config/Cryptomator/ipcPort.bin"), //
Paths.get("/home/testuser/.Cryptomator/ipcPort.bin")));
@@ -54,7 +54,7 @@ class EnvironmentTest {
public void testKeychainPath() {
System.setProperty("cryptomator.keychainPath", "~/AppData/Roaming/Cryptomator/keychain.json");
List<Path> result = env.getKeychainPath().collect(Collectors.toList());
List<Path> result = env.getKeychainPath().toList();
MatcherAssert.assertThat(result, Matchers.hasSize(1));
MatcherAssert.assertThat(result, Matchers.contains(Paths.get("/home/testuser/AppData/Roaming/Cryptomator/keychain.json")));
}
@@ -88,7 +88,7 @@ class EnvironmentTest {
@DisplayName("test.path.property=")
public void testEmptyList() {
System.setProperty("test.path.property", "");
List<Path> result = env.getPaths("test.path.property").collect(Collectors.toList());
List<Path> result = env.getPaths("test.path.property").toList();
MatcherAssert.assertThat(result, Matchers.hasSize(0));
}
@@ -97,7 +97,7 @@ class EnvironmentTest {
@DisplayName("test.path.property=/foo/bar/test")
public void testSingleAbsolutePath() {
System.setProperty("test.path.property", "/foo/bar/test");
List<Path> result = env.getPaths("test.path.property").collect(Collectors.toList());
List<Path> result = env.getPaths("test.path.property").toList();
MatcherAssert.assertThat(result, Matchers.hasSize(1));
MatcherAssert.assertThat(result, Matchers.hasItem(Paths.get("/foo/bar/test")));
@@ -107,7 +107,7 @@ class EnvironmentTest {
@DisplayName("test.path.property=~/test")
public void testSingleHomeRelativePath() {
System.setProperty("test.path.property", "~/test");
List<Path> result = env.getPaths("test.path.property").collect(Collectors.toList());
List<Path> result = env.getPaths("test.path.property").toList();
MatcherAssert.assertThat(result, Matchers.hasSize(1));
MatcherAssert.assertThat(result, Matchers.hasItem(Paths.get("/home/testuser/test")));
@@ -117,7 +117,7 @@ class EnvironmentTest {
@DisplayName("test.path.property=~/test:~/test2:/foo/bar/test")
public void testMultiplePaths() {
System.setProperty("test.path.property", "~/test:~/test2:/foo/bar/test");
List<Path> result = env.getPaths("test.path.property").collect(Collectors.toList());
List<Path> result = env.getPaths("test.path.property").toList();
MatcherAssert.assertThat(result, Matchers.hasSize(3));
MatcherAssert.assertThat(result, Matchers.contains(Paths.get("/home/testuser/test"), //
@@ -9,10 +9,12 @@ import java.util.Optional;
class LicenseCheckerTest {
private static final String PUBLIC_KEY = "MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQBgc4HZz+/fBbC7lmEww0AO3NK9wVZ" //
+ "PDZ0VEnsaUFLEYpTzb90nITtJUcPUbvOsdZIZ1Q8fnbquAYgxXL5UgHMoywAib47" //
+ "6MkyyYgPk0BXZq3mq4zImTRNuaU9slj9TVJ3ScT3L1bXwVuPJDzpr5GOFpaj+WwM" //
+ "Al8G7CqwoJOsW7Kddns=";
private static final String PUBLIC_KEY = """
MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQBgc4HZz+/fBbC7lmEww0AO3NK9wVZ\
PDZ0VEnsaUFLEYpTzb90nITtJUcPUbvOsdZIZ1Q8fnbquAYgxXL5UgHMoywAib47\
6MkyyYgPk0BXZq3mq4zImTRNuaU9slj9TVJ3ScT3L1bXwVuPJDzpr5GOFpaj+WwM\
Al8G7CqwoJOsW7Kddns=\
""";
private LicenseChecker licenseChecker;
@@ -44,4 +44,9 @@ class MapKeychainAccess implements KeychainAccessProvider {
return true;
}
@Override
public boolean isLocked() {
return false;
}
}
@@ -21,13 +21,18 @@ public class SettingsJsonAdapterTest {
@Test
public void testDeserialize() throws IOException {
String vault1Json = "{\"id\": \"1\", \"path\": \"/vault1\", \"mountName\": \"vault1\", \"winDriveLetter\": \"X\"}";
String vault2Json = "{\"id\": \"2\", \"path\": \"/vault2\", \"mountName\": \"vault2\", \"winDriveLetter\": \"Y\"}";
String json = "{\"directories\": [" + vault1Json + "," + vault2Json + "]," //
+ "\"checkForUpdatesEnabled\": true,"//
+ "\"port\": 8080,"//
+ "\"numTrayNotifications\": 42,"//
+ "\"preferredVolumeImpl\": \"FUSE\"}";
String json = """
{
"directories": [
{"id": "1", "path": "/vault1", "mountName": "vault1", "winDriveLetter": "X"},
{"id": "2", "path": "/vault2", "mountName": "vault2", "winDriveLetter": "Y"}
],
"checkForUpdatesEnabled": true,
"port": 8080,
"numTrayNotifications": 42,
"preferredVolumeImpl": "FUSE"
}
""";
Settings settings = adapter.fromJson(json);
@@ -41,7 +41,7 @@ class FileOpenRequestHandler {
}
private void openFiles(OpenFilesEvent evt) {
Collection<Path> pathsToOpen = evt.getFiles().stream().map(File::toPath).collect(Collectors.toList());
Collection<Path> pathsToOpen = evt.getFiles().stream().map(File::toPath).toList();
AppLaunchEvent launchEvent = new AppLaunchEvent(AppLaunchEvent.EventType.OPEN_FILE, pathsToOpen);
tryToEnqueueFileOpenRequest(launchEvent);
}
@@ -59,7 +59,7 @@ class FileOpenRequestHandler {
LOG.trace("Argument not a valid path: {}", str);
return null;
}
}).filter(Objects::nonNull).collect(Collectors.toList());
}).filter(Objects::nonNull).toList();
if (!pathsToOpen.isEmpty()) {
AppLaunchEvent launchEvent = new AppLaunchEvent(AppLaunchEvent.EventType.OPEN_FILE, pathsToOpen);
tryToEnqueueFileOpenRequest(launchEvent);
@@ -47,8 +47,8 @@ public class LoggerModule {
@Singleton
static LoggerContext provideLoggerContext() {
ILoggerFactory loggerFactory = LoggerFactory.getILoggerFactory();
if (loggerFactory instanceof LoggerContext) {
return (LoggerContext) loggerFactory;
if (loggerFactory instanceof LoggerContext context) {
return context;
} else {
throw new IllegalStateException("SLF4J not bound to Logback.");
}
+13 -25
View File
@@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.cryptomator</groupId>
<artifactId>main</artifactId>
<version>1.5.12</version>
<version>1.6.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Cryptomator</name>
@@ -22,24 +22,25 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.jdk.version>16</project.jdk.version>
<!-- cryptomator dependencies -->
<cryptomator.cryptofs.version>1.9.13</cryptomator.cryptofs.version>
<cryptomator.integrations.version>0.1.6</cryptomator.integrations.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.1</cryptomator.integrations.linux.version>
<cryptomator.fuse.version>1.2.8</cryptomator.fuse.version>
<cryptomator.dokany.version>1.2.3</cryptomator.dokany.version>
<cryptomator.webdav.version>1.1.1</cryptomator.webdav.version>
<cryptomator.cryptofs.version>1.9.14</cryptomator.cryptofs.version>
<cryptomator.integrations.version>1.0.0-beta2</cryptomator.integrations.version>
<cryptomator.integrations.win.version>1.0.0-beta2</cryptomator.integrations.win.version>
<cryptomator.integrations.mac.version>1.0.0-beta2</cryptomator.integrations.mac.version>
<cryptomator.integrations.linux.version>1.0.0-beta1</cryptomator.integrations.linux.version>
<cryptomator.fuse.version>1.3.0</cryptomator.fuse.version>
<cryptomator.dokany.version>1.2.4</cryptomator.dokany.version>
<cryptomator.webdav.version>1.2.0</cryptomator.webdav.version>
<!-- 3rd party dependencies -->
<javafx.version>15</javafx.version>
<commons-lang3.version>3.11</commons-lang3.version>
<jwt.version>3.12.0</jwt.version>
<jwt.version>3.13.0</jwt.version>
<easybind.version>2.1.0</easybind.version>
<guava.version>30.0-jre</guava.version>
<dagger.version>2.29.1</dagger.version>
<dagger.version>2.32</dagger.version>
<gson.version>2.8.6</gson.version>
<slf4j.version>1.7.30</slf4j.version>
<logback.version>1.2.3</logback.version>
@@ -50,13 +51,6 @@
<hamcrest.version>2.2</hamcrest.version>
</properties>
<repositories>
<repository>
<id>jcenter</id>
<url>https://jcenter.bintray.com</url>
</repository>
</repositories>
<dependencyManagement>
<dependencies>
<!-- modules -->
@@ -224,12 +218,6 @@
<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>
@@ -437,7 +425,7 @@
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<release>14</release>
<release>${project.jdk.version}</release>
<annotationProcessorPaths>
<path>
<groupId>com.google.dagger</groupId>
-5
View File
@@ -1,11 +1,6 @@
<?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>
@@ -6,7 +6,7 @@ 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.FxmlLoaderFactory;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.common.FxControllerKey;
import org.cryptomator.ui.common.FxmlFile;
@@ -43,8 +43,8 @@ public abstract class AddVaultModule {
@Provides
@AddVaultWizardWindow
@AddVaultWizardScoped
static FXMLLoaderFactory provideFxmlLoaderFactory(Map<Class<? extends FxController>, Provider<FxController>> factories, DefaultSceneFactory sceneFactory, ResourceBundle resourceBundle) {
return new FXMLLoaderFactory(factories, sceneFactory, resourceBundle);
static FxmlLoaderFactory provideFxmlLoaderFactory(Map<Class<? extends FxController>, Provider<FxController>> factories, DefaultSceneFactory sceneFactory, ResourceBundle resourceBundle) {
return new FxmlLoaderFactory(factories, sceneFactory, resourceBundle);
}
@Provides
@@ -91,50 +91,50 @@ public abstract class AddVaultModule {
@Provides
@FxmlScene(FxmlFile.ADDVAULT_WELCOME)
@AddVaultWizardScoped
static Scene provideWelcomeScene(@AddVaultWizardWindow FXMLLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene(FxmlFile.ADDVAULT_WELCOME.getRessourcePathString());
static Scene provideWelcomeScene(@AddVaultWizardWindow FxmlLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene(FxmlFile.ADDVAULT_WELCOME);
}
@Provides
@FxmlScene(FxmlFile.ADDVAULT_EXISTING)
@AddVaultWizardScoped
static Scene provideChooseExistingVaultScene(@AddVaultWizardWindow FXMLLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene(FxmlFile.ADDVAULT_EXISTING.getRessourcePathString());
static Scene provideChooseExistingVaultScene(@AddVaultWizardWindow FxmlLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene(FxmlFile.ADDVAULT_EXISTING);
}
@Provides
@FxmlScene(FxmlFile.ADDVAULT_NEW_NAME)
@AddVaultWizardScoped
static Scene provideCreateNewVaultNameScene(@AddVaultWizardWindow FXMLLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene(FxmlFile.ADDVAULT_NEW_NAME.getRessourcePathString());
static Scene provideCreateNewVaultNameScene(@AddVaultWizardWindow FxmlLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene(FxmlFile.ADDVAULT_NEW_NAME);
}
@Provides
@FxmlScene(FxmlFile.ADDVAULT_NEW_LOCATION)
@AddVaultWizardScoped
static Scene provideCreateNewVaultLocationScene(@AddVaultWizardWindow FXMLLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene(FxmlFile.ADDVAULT_NEW_LOCATION.getRessourcePathString());
static Scene provideCreateNewVaultLocationScene(@AddVaultWizardWindow FxmlLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene(FxmlFile.ADDVAULT_NEW_LOCATION);
}
@Provides
@FxmlScene(FxmlFile.ADDVAULT_NEW_PASSWORD)
@AddVaultWizardScoped
static Scene provideCreateNewVaultPasswordScene(@AddVaultWizardWindow FXMLLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene(FxmlFile.ADDVAULT_NEW_PASSWORD.getRessourcePathString());
static Scene provideCreateNewVaultPasswordScene(@AddVaultWizardWindow FxmlLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene(FxmlFile.ADDVAULT_NEW_PASSWORD);
}
@Provides
@FxmlScene(FxmlFile.ADDVAULT_NEW_RECOVERYKEY)
@AddVaultWizardScoped
static Scene provideCreateNewVaultRecoveryKeyScene(@AddVaultWizardWindow FXMLLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene(FxmlFile.ADDVAULT_NEW_RECOVERYKEY.getRessourcePathString());
static Scene provideCreateNewVaultRecoveryKeyScene(@AddVaultWizardWindow FxmlLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene(FxmlFile.ADDVAULT_NEW_RECOVERYKEY);
}
@Provides
@FxmlScene(FxmlFile.ADDVAULT_SUCCESS)
@AddVaultWizardScoped
static Scene provideCreateNewVaultSuccessScene(@AddVaultWizardWindow FXMLLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene(FxmlFile.ADDVAULT_SUCCESS.getRessourcePathString());
static Scene provideCreateNewVaultSuccessScene(@AddVaultWizardWindow FxmlLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene(FxmlFile.ADDVAULT_SUCCESS);
}
// ------------------
@@ -4,7 +4,7 @@ import dagger.Lazy;
import org.apache.commons.lang3.SystemUtils;
import org.cryptomator.common.vaults.Vault;
import org.cryptomator.common.vaults.VaultListManager;
import org.cryptomator.ui.common.ErrorComponent;
import org.cryptomator.ui.error.GenericErrorComponent;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.common.FxmlFile;
import org.cryptomator.ui.common.FxmlScene;
@@ -34,7 +34,7 @@ public class ChooseExistingVaultController implements FxController {
private final Stage window;
private final Lazy<Scene> welcomeScene;
private final Lazy<Scene> successScene;
private final ErrorComponent.Builder errorComponent;
private final GenericErrorComponent.Builder genericErrorBuilder;
private final ObjectProperty<Path> vaultPath;
private final ObjectProperty<Vault> vault;
private final VaultListManager vaultListManager;
@@ -43,11 +43,11 @@ public class ChooseExistingVaultController implements FxController {
private Image screenshot;
@Inject
ChooseExistingVaultController(@AddVaultWizardWindow Stage window, @FxmlScene(FxmlFile.ADDVAULT_WELCOME) Lazy<Scene> welcomeScene, @FxmlScene(FxmlFile.ADDVAULT_SUCCESS) Lazy<Scene> successScene, ErrorComponent.Builder errorComponent, ObjectProperty<Path> vaultPath, @AddVaultWizardWindow ObjectProperty<Vault> vault, VaultListManager vaultListManager, ResourceBundle resourceBundle) {
ChooseExistingVaultController(@AddVaultWizardWindow Stage window, @FxmlScene(FxmlFile.ADDVAULT_WELCOME) Lazy<Scene> welcomeScene, @FxmlScene(FxmlFile.ADDVAULT_SUCCESS) Lazy<Scene> successScene, GenericErrorComponent.Builder genericErrorBuilder, ObjectProperty<Path> vaultPath, @AddVaultWizardWindow ObjectProperty<Vault> vault, VaultListManager vaultListManager, ResourceBundle resourceBundle) {
this.window = window;
this.welcomeScene = welcomeScene;
this.successScene = successScene;
this.errorComponent = errorComponent;
this.genericErrorBuilder = genericErrorBuilder;
this.vaultPath = vaultPath;
this.vault = vault;
this.vaultListManager = vaultListManager;
@@ -83,7 +83,7 @@ public class ChooseExistingVaultController implements FxController {
window.setScene(successScene.get());
} catch (NoSuchFileException e) {
LOG.error("Failed to open existing vault.", e);
errorComponent.cause(e).window(window).returnToScene(window.getScene()).build().showErrorScene();
genericErrorBuilder.cause(e).window(window).returnToScene(window.getScene()).build().showErrorScene();
}
}
}
@@ -1,7 +1,7 @@
package org.cryptomator.ui.addvaultwizard;
import dagger.Lazy;
import org.cryptomator.ui.common.ErrorComponent;
import org.cryptomator.ui.error.GenericErrorComponent;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.common.FxmlFile;
import org.cryptomator.ui.common.FxmlScene;
@@ -43,7 +43,7 @@ public class CreateNewVaultLocationController implements FxController {
private final Stage window;
private final Lazy<Scene> chooseNameScene;
private final Lazy<Scene> choosePasswordScene;
private final ErrorComponent.Builder errorComponent;
private final GenericErrorComponent.Builder genericErrorBuilder;
private final LocationPresets locationPresets;
private final ObjectProperty<Path> vaultPath;
private final StringProperty vaultName;
@@ -61,11 +61,11 @@ public class CreateNewVaultLocationController implements FxController {
public RadioButton customRadioButton;
@Inject
CreateNewVaultLocationController(@AddVaultWizardWindow Stage window, @FxmlScene(FxmlFile.ADDVAULT_NEW_NAME) Lazy<Scene> chooseNameScene, @FxmlScene(FxmlFile.ADDVAULT_NEW_PASSWORD) Lazy<Scene> choosePasswordScene, ErrorComponent.Builder errorComponent, LocationPresets locationPresets, ObjectProperty<Path> vaultPath, @Named("vaultName") StringProperty vaultName, ResourceBundle resourceBundle) {
CreateNewVaultLocationController(@AddVaultWizardWindow Stage window, @FxmlScene(FxmlFile.ADDVAULT_NEW_NAME) Lazy<Scene> chooseNameScene, @FxmlScene(FxmlFile.ADDVAULT_NEW_PASSWORD) Lazy<Scene> choosePasswordScene, GenericErrorComponent.Builder genericErrorBuilder, LocationPresets locationPresets, ObjectProperty<Path> vaultPath, @Named("vaultName") StringProperty vaultName, ResourceBundle resourceBundle) {
this.window = window;
this.chooseNameScene = chooseNameScene;
this.choosePasswordScene = choosePasswordScene;
this.errorComponent = errorComponent;
this.genericErrorBuilder = genericErrorBuilder;
this.locationPresets = locationPresets;
this.vaultPath = vaultPath;
this.vaultName = vaultName;
@@ -129,7 +129,7 @@ public class CreateNewVaultLocationController implements FxController {
warningText.set(resourceBundle.getString("addvaultwizard.new.locationDoesNotExist"));
} catch (IOException e) {
LOG.error("Failed to create and delete directory at chosen vault path.", e);
errorComponent.cause(e).window(window).returnToScene(window.getScene()).build().showErrorScene();
genericErrorBuilder.cause(e).window(window).returnToScene(window.getScene()).build().showErrorScene();
}
}
@@ -5,7 +5,7 @@ import org.cryptomator.common.vaults.Vault;
import org.cryptomator.common.vaults.VaultListManager;
import org.cryptomator.cryptofs.CryptoFileSystemProperties;
import org.cryptomator.cryptofs.CryptoFileSystemProvider;
import org.cryptomator.ui.common.ErrorComponent;
import org.cryptomator.ui.error.GenericErrorComponent;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.common.FxmlFile;
import org.cryptomator.ui.common.FxmlScene;
@@ -53,7 +53,7 @@ public class CreateNewVaultPasswordController implements FxController {
private final Lazy<Scene> chooseLocationScene;
private final Lazy<Scene> recoveryKeyScene;
private final Lazy<Scene> successScene;
private final ErrorComponent.Builder errorComponent;
private final GenericErrorComponent.Builder genericErrorBuilder;
private final ExecutorService executor;
private final RecoveryKeyFactory recoveryKeyFactory;
private final StringProperty vaultNameProperty;
@@ -73,12 +73,12 @@ public class CreateNewVaultPasswordController implements FxController {
public Toggle skipRecoveryKey;
@Inject
CreateNewVaultPasswordController(@AddVaultWizardWindow Stage window, @FxmlScene(FxmlFile.ADDVAULT_NEW_LOCATION) Lazy<Scene> chooseLocationScene, @FxmlScene(FxmlFile.ADDVAULT_NEW_RECOVERYKEY) Lazy<Scene> recoveryKeyScene, @FxmlScene(FxmlFile.ADDVAULT_SUCCESS) Lazy<Scene> successScene, ErrorComponent.Builder errorComponent, ExecutorService executor, RecoveryKeyFactory recoveryKeyFactory, @Named("vaultName") StringProperty vaultName, ObjectProperty<Path> vaultPath, @AddVaultWizardWindow ObjectProperty<Vault> vault, @Named("recoveryKey") StringProperty recoveryKey, VaultListManager vaultListManager, ResourceBundle resourceBundle, @Named("newPassword") ObjectProperty<CharSequence> password, ReadmeGenerator readmeGenerator) {
CreateNewVaultPasswordController(@AddVaultWizardWindow Stage window, @FxmlScene(FxmlFile.ADDVAULT_NEW_LOCATION) Lazy<Scene> chooseLocationScene, @FxmlScene(FxmlFile.ADDVAULT_NEW_RECOVERYKEY) Lazy<Scene> recoveryKeyScene, @FxmlScene(FxmlFile.ADDVAULT_SUCCESS) Lazy<Scene> successScene, GenericErrorComponent.Builder genericErrorBuilder, ExecutorService executor, RecoveryKeyFactory recoveryKeyFactory, @Named("vaultName") StringProperty vaultName, ObjectProperty<Path> vaultPath, @AddVaultWizardWindow ObjectProperty<Vault> vault, @Named("recoveryKey") StringProperty recoveryKey, VaultListManager vaultListManager, ResourceBundle resourceBundle, @Named("newPassword") ObjectProperty<CharSequence> password, ReadmeGenerator readmeGenerator) {
this.window = window;
this.chooseLocationScene = chooseLocationScene;
this.recoveryKeyScene = recoveryKeyScene;
this.successScene = successScene;
this.errorComponent = errorComponent;
this.genericErrorBuilder = genericErrorBuilder;
this.executor = executor;
this.recoveryKeyFactory = recoveryKeyFactory;
this.vaultNameProperty = vaultName;
@@ -113,7 +113,7 @@ public class CreateNewVaultPasswordController implements FxController {
Files.createDirectory(pathToVault);
} catch (IOException e) {
LOG.error("Failed to create vault directory.", e);
errorComponent.cause(e).window(window).returnToScene(window.getScene()).build().showErrorScene();
genericErrorBuilder.cause(e).window(window).returnToScene(window.getScene()).build().showErrorScene();
return;
}
@@ -138,7 +138,7 @@ public class CreateNewVaultPasswordController implements FxController {
window.setScene(recoveryKeyScene.get());
}).onError(IOException.class, e -> {
LOG.error("Failed to initialize vault.", e);
errorComponent.cause(e).window(window).returnToScene(window.getScene()).build().showErrorScene();
genericErrorBuilder.cause(e).window(window).returnToScene(window.getScene()).build().showErrorScene();
}).andFinally(() -> {
processing.set(false);
}).runOnce(executor);
@@ -154,7 +154,7 @@ public class CreateNewVaultPasswordController implements FxController {
window.setScene(successScene.get());
}).onError(IOException.class, e -> {
LOG.error("Failed to initialize vault.", e);
errorComponent.cause(e).window(window).returnToScene(window.getScene()).build().showErrorScene();
genericErrorBuilder.cause(e).window(window).returnToScene(window.getScene()).build().showErrorScene();
}).andFinally(() -> {
processing.set(false);
}).runOnce(executor);
@@ -6,7 +6,7 @@ import org.cryptomator.cryptofs.CryptoFileSystemProvider;
import org.cryptomator.cryptolib.api.InvalidPassphraseException;
import org.cryptomator.integrations.keychain.KeychainAccessException;
import org.cryptomator.ui.common.Animations;
import org.cryptomator.ui.common.ErrorComponent;
import org.cryptomator.ui.error.GenericErrorComponent;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.controls.NiceSecurePasswordField;
import org.slf4j.Logger;
@@ -23,7 +23,6 @@ import javafx.scene.control.CheckBox;
import javafx.stage.Stage;
import java.io.IOException;
import java.nio.CharBuffer;
import java.util.Optional;
import static org.cryptomator.common.Constants.MASTERKEY_FILENAME;
@@ -35,7 +34,7 @@ public class ChangePasswordController implements FxController {
private final Stage window;
private final Vault vault;
private final ObjectProperty<CharSequence> newPassword;
private final ErrorComponent.Builder errorComponent;
private final GenericErrorComponent.Builder genericErrorBuilder;
private final KeychainManager keychain;
public NiceSecurePasswordField oldPasswordField;
@@ -43,11 +42,11 @@ public class ChangePasswordController implements FxController {
public Button finishButton;
@Inject
public ChangePasswordController(@ChangePasswordWindow Stage window, @ChangePasswordWindow Vault vault, @Named("newPassword") ObjectProperty<CharSequence> newPassword, ErrorComponent.Builder errorComponent, KeychainManager keychain) {
public ChangePasswordController(@ChangePasswordWindow Stage window, @ChangePasswordWindow Vault vault, @Named("newPassword") ObjectProperty<CharSequence> newPassword, GenericErrorComponent.Builder genericErrorBuilder, KeychainManager keychain) {
this.window = window;
this.vault = vault;
this.newPassword = newPassword;
this.errorComponent = errorComponent;
this.genericErrorBuilder = genericErrorBuilder;
this.keychain = keychain;
}
@@ -73,7 +72,7 @@ public class ChangePasswordController implements FxController {
updatePasswordInSystemkeychain();
} catch (IOException e) {
LOG.error("IO error occured during password change. Unable to perform operation.", e);
errorComponent.cause(e).window(window).returnToScene(window.getScene()).build().showErrorScene();
genericErrorBuilder.cause(e).window(window).returnToScene(window.getScene()).build().showErrorScene();
} catch (InvalidPassphraseException e) {
Animations.createShakeWindowAnimation(window).play();
oldPasswordField.selectAll();
@@ -5,7 +5,7 @@ import dagger.Module;
import dagger.Provides;
import dagger.multibindings.IntoMap;
import org.cryptomator.ui.common.DefaultSceneFactory;
import org.cryptomator.ui.common.FXMLLoaderFactory;
import org.cryptomator.ui.common.FxmlLoaderFactory;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.common.FxControllerKey;
import org.cryptomator.ui.common.FxmlFile;
@@ -37,8 +37,8 @@ abstract class ChangePasswordModule {
@Provides
@ChangePasswordWindow
@ChangePasswordScoped
static FXMLLoaderFactory provideFxmlLoaderFactory(Map<Class<? extends FxController>, Provider<FxController>> factories, DefaultSceneFactory sceneFactory, ResourceBundle resourceBundle) {
return new FXMLLoaderFactory(factories, sceneFactory, resourceBundle);
static FxmlLoaderFactory provideFxmlLoaderFactory(Map<Class<? extends FxController>, Provider<FxController>> factories, DefaultSceneFactory sceneFactory, ResourceBundle resourceBundle) {
return new FxmlLoaderFactory(factories, sceneFactory, resourceBundle);
}
@Provides
@@ -56,8 +56,8 @@ abstract class ChangePasswordModule {
@Provides
@FxmlScene(FxmlFile.CHANGEPASSWORD)
@ChangePasswordScoped
static Scene provideUnlockScene(@ChangePasswordWindow FXMLLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene("/fxml/changepassword.fxml");
static Scene provideUnlockScene(@ChangePasswordWindow FxmlLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene(FxmlFile.CHANGEPASSWORD);
}
@@ -42,8 +42,8 @@ public class DefaultSceneFactory implements Function<Parent, Scene> {
protected void configureScene(Scene scene) {
scene.windowProperty().addListener(observable -> {
Window window = scene.getWindow();
if (window instanceof Stage) {
setupDefaultAccelerators(scene, (Stage) window);
if (window instanceof Stage s) {
setupDefaultAccelerators(scene, s);
}
});
}
@@ -1,49 +0,0 @@
package org.cryptomator.ui.common;
import dagger.BindsInstance;
import dagger.Subcomponent;
import javax.annotation.Nullable;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.stage.Stage;
@Subcomponent(modules = {ErrorModule.class})
public interface ErrorComponent {
Stage window();
@FxmlScene(FxmlFile.ERROR)
Scene scene();
default void showErrorScene() {
if (Platform.isFxApplicationThread()) {
show();
} else {
Platform.runLater(this::show);
}
}
private void show() {
Stage stage = window();
stage.setScene(scene());
stage.show();
}
@Subcomponent.Builder
interface Builder {
@BindsInstance
Builder cause(Throwable cause);
@BindsInstance
Builder window(Stage window);
@BindsInstance
Builder returnToScene(@Nullable Scene previousScene);
ErrorComponent build();
}
}
@@ -1,44 +0,0 @@
package org.cryptomator.ui.common;
import javax.annotation.Nullable;
import javax.inject.Inject;
import javax.inject.Named;
import javafx.fxml.FXML;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class ErrorController implements FxController {
private final String stackTrace;
private final Scene previousScene;
private final Stage window;
@Inject
ErrorController(@Named("stackTrace") String stackTrace, @Nullable Scene previousScene, Stage window) {
this.stackTrace = stackTrace;
this.previousScene = previousScene;
this.window = window;
}
@FXML
public void back() {
if (previousScene != null) {
window.setScene(previousScene);
}
}
@FXML
public void close() {
window.close();
}
/* Getter/Setter */
public boolean isPreviousScenePresent() {
return previousScene != null;
}
public String getStackTrace() {
return stackTrace;
}
}
@@ -9,8 +9,8 @@ public enum FxmlFile {
ADDVAULT_SUCCESS("/fxml/addvault_success.fxml"), //
ADDVAULT_WELCOME("/fxml/addvault_welcome.fxml"), //
CHANGEPASSWORD("/fxml/changepassword.fxml"), //
ERROR("/fxml/error.fxml"), //
FORGET_PASSWORD("/fxml/forget_password.fxml"), //
GENERIC_ERROR("/fxml/generic_error.fxml"), //
LOCK_FORCED("/fxml/lock_forced.fxml"), //
LOCK_FAILED("/fxml/lock_failed.fxml"), //
MAIN_WINDOW("/fxml/main_window.fxml"), //
@@ -39,7 +39,7 @@ public enum FxmlFile {
this.ressourcePathString = ressourcePathString;
}
public String getRessourcePathString() {
String getRessourcePathString() {
return ressourcePathString;
}
}
@@ -11,13 +11,13 @@ import java.util.Map;
import java.util.ResourceBundle;
import java.util.function.Function;
public class FXMLLoaderFactory {
public class FxmlLoaderFactory {
private final Map<Class<? extends FxController>, Provider<FxController>> controllerFactories;
private final Function<Parent, Scene> sceneFactory;
private final ResourceBundle resourceBundle;
public FXMLLoaderFactory(Map<Class<? extends FxController>, Provider<FxController>> controllerFactories, Function<Parent, Scene> sceneFactory, ResourceBundle resourceBundle) {
public FxmlLoaderFactory(Map<Class<? extends FxController>, Provider<FxController>> controllerFactories, Function<Parent, Scene> sceneFactory, ResourceBundle resourceBundle) {
this.controllerFactories = controllerFactories;
this.sceneFactory = sceneFactory;
this.resourceBundle = resourceBundle;
@@ -48,13 +48,17 @@ public class FXMLLoaderFactory {
return loader;
}
public Scene createScene(FxmlFile fxmlFile) {
return createScene(fxmlFile.getRessourcePathString());
}
/**
* {@link #load(String) Loads} the FXML file and creates a new Scene containing the loaded ui.
*
* @param fxmlResourceName Name of the resource (as in {@link Class#getResource(String)}).
* @throws UncheckedIOException wrapping any IOException thrown by {@link #load(String)).
*/
public Scene createScene(String fxmlResourceName) {
private Scene createScene(String fxmlResourceName) {
final FXMLLoader loader;
try {
loader = load(fxmlResourceName);
@@ -0,0 +1,35 @@
package org.cryptomator.ui.error;
import org.cryptomator.ui.common.FxController;
import javax.annotation.Nullable;
import javafx.fxml.FXML;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class AbstractErrorController implements FxController {
protected final Stage window;
protected final Scene returnScene;
public AbstractErrorController(@ErrorReport Stage window, @ErrorReport @Nullable Scene returnScene) {
this.returnScene = returnScene;
this.window = window;
}
@FXML
public void back() {
if (this.returnScene != null) {
this.window.setScene(this.returnScene);
}
}
@FXML
public void close() {
this.window.close();
}
public boolean isReturnScenePresent() {
return this.returnScene != null;
}
}
@@ -0,0 +1,53 @@
package org.cryptomator.ui.error;
import dagger.BindsInstance;
import javax.annotation.Nullable;
import javax.inject.Named;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.stage.Stage;
public interface ErrorComponentBase {
@ErrorReport
Stage window();
@Named("errorScene")
Scene errorScene();
@ErrorReport
Throwable cause();
@ErrorReport
@Nullable
Scene previousScene();
default void showErrorScene() {
if (Platform.isFxApplicationThread()) {
show();
} else {
Platform.runLater(this::show);
}
}
private void show() {
Stage stage = window();
stage.setScene(errorScene());
stage.show();
}
interface BuilderBase<B, C> {
@BindsInstance
B window(@ErrorReport Stage window);
@BindsInstance
B cause(@ErrorReport Throwable cause);
@BindsInstance
B returnToScene(@ErrorReport @Nullable Scene returnScene);
C build();
}
}
@@ -1,9 +1,11 @@
package org.cryptomator.ui.common;
package org.cryptomator.ui.error;
import dagger.Binds;
import dagger.Module;
import dagger.Provides;
import dagger.multibindings.IntoMap;
import org.cryptomator.ui.common.DefaultSceneFactory;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.common.FxmlFile;
import org.cryptomator.ui.common.FxmlLoaderFactory;
import javax.inject.Named;
import javax.inject.Provider;
@@ -18,29 +20,22 @@ import java.util.ResourceBundle;
abstract class ErrorModule {
@Provides
static FXMLLoaderFactory provideFxmlLoaderFactory(Map<Class<? extends FxController>, Provider<FxController>> factories, DefaultSceneFactory sceneFactory, ResourceBundle resourceBundle) {
return new FXMLLoaderFactory(factories, sceneFactory, resourceBundle);
static FxmlLoaderFactory provideFxmlLoaderFactory(Map<Class<? extends FxController>, Provider<FxController>> factories, DefaultSceneFactory sceneFactory, ResourceBundle resourceBundle) {
return new FxmlLoaderFactory(factories, sceneFactory, resourceBundle);
}
@Provides
@Named("stackTrace")
static String provideStackTrace(Throwable cause) {
static String provideStackTrace(@ErrorReport Throwable cause) {
// TODO deduplicate VaultDetailUnknownErrorController.java
ByteArrayOutputStream baos = new ByteArrayOutputStream();
cause.printStackTrace(new PrintStream(baos));
return baos.toString(StandardCharsets.UTF_8);
}
@Binds
@IntoMap
@FxControllerKey(ErrorController.class)
abstract FxController bindErrorController(ErrorController controller);
@Provides
@FxmlScene(FxmlFile.ERROR)
static Scene provideErrorScene(FXMLLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene(FxmlFile.ERROR.getRessourcePathString());
@Named("errorScene")
static Scene provideErrorScene(FxmlLoaderFactory fxmlLoaders, @ErrorReport FxmlFile file) {
return fxmlLoaders.createScene(file);
}
}
@@ -0,0 +1,14 @@
package org.cryptomator.ui.error;
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)
public @interface ErrorReport {
}
@@ -0,0 +1,32 @@
package org.cryptomator.ui.error;
import dagger.Binds;
import dagger.Module;
import dagger.Provides;
import dagger.Subcomponent;
import dagger.multibindings.IntoMap;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.common.FxControllerKey;
import org.cryptomator.ui.common.FxmlFile;
@Subcomponent(modules = {ErrorModule.class, GenericErrorComponent.GenericErrorModule.class})
public interface GenericErrorComponent extends ErrorComponentBase {
@Subcomponent.Builder
interface Builder extends BuilderBase<Builder, GenericErrorComponent> { /* Handled by base interface */ }
@Module
abstract class GenericErrorModule {
@Provides
@ErrorReport
static FxmlFile provideFxmlFile() {
return FxmlFile.GENERIC_ERROR;
}
@Binds
@IntoMap
@FxControllerKey(GenericErrorController.class)
abstract FxController bindController(GenericErrorController controller);
}
}
@@ -0,0 +1,24 @@
package org.cryptomator.ui.error;
import javax.annotation.Nullable;
import javax.inject.Inject;
import javax.inject.Named;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class GenericErrorController extends AbstractErrorController {
private final String stackTrace;
@Inject
GenericErrorController(@ErrorReport Stage window, @ErrorReport @Nullable Scene previousScene, @Named("stackTrace") String stackTrace) {
super(window, previousScene);
this.stackTrace = stackTrace;
}
/* Getter/Setter */
public String getStackTrace() {
return this.stackTrace;
}
}
@@ -0,0 +1,42 @@
package org.cryptomator.ui.error;
import dagger.Binds;
import dagger.BindsInstance;
import dagger.Module;
import dagger.Provides;
import dagger.Subcomponent;
import dagger.multibindings.IntoMap;
import org.cryptomator.common.vaults.Vault;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.common.FxControllerKey;
import org.cryptomator.ui.common.FxmlFile;
import org.cryptomator.ui.unlock.UnlockInvalidMountPointController;
import org.cryptomator.ui.unlock.UnlockScoped;
@Subcomponent(modules = {ErrorModule.class, InvalidMountPointExceptionComponent.InvalidMountPointExceptionModule.class})
@UnlockScoped
public interface InvalidMountPointExceptionComponent extends ErrorComponentBase {
@Subcomponent.Builder
interface Builder extends BuilderBase<Builder, InvalidMountPointExceptionComponent> {
@BindsInstance
Builder vault(@ErrorReport Vault vault);
}
@Module
abstract class InvalidMountPointExceptionModule {
@Provides
@ErrorReport
static FxmlFile provideFxmlFile() {
return FxmlFile.UNLOCK_INVALID_MOUNT_POINT;
}
@Binds
@IntoMap
@FxControllerKey(UnlockInvalidMountPointController.class)
abstract FxController bindController(UnlockInvalidMountPointController controller);
}
}
@@ -5,7 +5,7 @@ import dagger.Module;
import dagger.Provides;
import dagger.multibindings.IntoMap;
import org.cryptomator.ui.common.DefaultSceneFactory;
import org.cryptomator.ui.common.FXMLLoaderFactory;
import org.cryptomator.ui.common.FxmlLoaderFactory;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.common.FxControllerKey;
import org.cryptomator.ui.common.FxmlFile;
@@ -29,8 +29,8 @@ abstract class ForgetPasswordModule {
@Provides
@ForgetPasswordWindow
@ForgetPasswordScoped
static FXMLLoaderFactory provideFxmlLoaderFactory(Map<Class<? extends FxController>, Provider<FxController>> factories, DefaultSceneFactory sceneFactory, ResourceBundle resourceBundle) {
return new FXMLLoaderFactory(factories, sceneFactory, resourceBundle);
static FxmlLoaderFactory provideFxmlLoaderFactory(Map<Class<? extends FxController>, Provider<FxController>> factories, DefaultSceneFactory sceneFactory, ResourceBundle resourceBundle) {
return new FxmlLoaderFactory(factories, sceneFactory, resourceBundle);
}
@Provides
@@ -62,8 +62,8 @@ abstract class ForgetPasswordModule {
@Provides
@FxmlScene(FxmlFile.FORGET_PASSWORD)
@ForgetPasswordScoped
static Scene provideForgetPasswordScene(@ForgetPasswordWindow FXMLLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene("/fxml/forget_password.fxml");
static Scene provideForgetPasswordScene(@ForgetPasswordWindow FxmlLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene(FxmlFile.FORGET_PASSWORD);
}
// ------------------
@@ -86,7 +86,7 @@ public class FxApplication extends Application {
}
private void hasVisibleStagesChanged(@SuppressWarnings("unused") ObservableValue<? extends Boolean> observableValue, @SuppressWarnings("unused") boolean oldValue, boolean newValue) {
LOG.warn("has visible stages: {}", newValue);
LOG.debug("has visible stages: {}", newValue);
if (newValue) {
trayIntegration.ifPresent(TrayIntegrationProvider::restoredFromTray);
} else {
@@ -137,13 +137,13 @@ public class FxApplication extends Application {
}
private void appThemeChanged(@SuppressWarnings("unused") ObservableValue<? extends UiTheme> observable, @SuppressWarnings("unused") UiTheme oldValue, UiTheme newValue) {
appearanceProvider.ifPresent(appearanceProvider -> {
if (appearanceProvider.isPresent() && oldValue == UiTheme.AUTOMATIC && newValue != UiTheme.AUTOMATIC) {
try {
appearanceProvider.removeListener(systemInterfaceThemeListener);
appearanceProvider.get().removeListener(systemInterfaceThemeListener);
} catch (UiAppearanceException e) {
LOG.error("Failed to disable automatic theme switching.");
}
});
}
loadSelectedStyleSheet(newValue);
}
@@ -9,8 +9,9 @@ import dagger.Binds;
import dagger.Module;
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.error.GenericErrorComponent;
import org.cryptomator.ui.error.InvalidMountPointExceptionComponent;
import org.cryptomator.ui.lock.LockComponent;
import org.cryptomator.ui.mainwindow.MainWindowComponent;
import org.cryptomator.ui.preferences.PreferencesComponent;
@@ -19,17 +20,15 @@ import org.cryptomator.ui.unlock.UnlockComponent;
import javax.inject.Named;
import javafx.application.Application;
import javafx.collections.ObservableSet;
import javafx.scene.image.Image;
import javafx.stage.Stage;
import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
import java.util.Collections;
import java.util.List;
@Module(includes = {UpdateCheckerModule.class}, subcomponents = {MainWindowComponent.class, PreferencesComponent.class, UnlockComponent.class, LockComponent.class, QuitComponent.class, ErrorComponent.class})
abstract class FxApplicationModule {
@Module(includes = {UpdateCheckerModule.class}, subcomponents = {MainWindowComponent.class, PreferencesComponent.class, UnlockComponent.class, LockComponent.class, QuitComponent.class, GenericErrorComponent.class, InvalidMountPointExceptionComponent.class})
public abstract class FxApplicationModule {
@Provides
@Named("windowIcons")
@@ -15,6 +15,7 @@ import javafx.beans.property.StringProperty;
import javafx.concurrent.ScheduledService;
import javafx.concurrent.Task;
import javafx.util.Duration;
import java.io.UncheckedIOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
@@ -39,8 +40,13 @@ public abstract class UpdateCheckerModule {
@Provides
@FxApplicationScoped
static HttpClient provideHttpClient() {
return HttpClient.newHttpClient();
static Optional<HttpClient> provideHttpClient() {
try {
return Optional.of(HttpClient.newHttpClient());
} catch (UncheckedIOException e) {
LOG.error("HttpClient for update check cannot be created.", e);
return Optional.empty();
}
}
@Provides
@@ -66,11 +72,20 @@ public abstract class UpdateCheckerModule {
@Provides
@FxApplicationScoped
static ScheduledService<String> provideCheckForUpdatesService(ExecutorService executor, HttpClient httpClient, HttpRequest checkForUpdatesRequest, @Named("checkForUpdatesInterval") ObjectBinding<Duration> period) {
static ScheduledService<String> provideCheckForUpdatesService(ExecutorService executor, Optional<HttpClient> httpClient, HttpRequest checkForUpdatesRequest, @Named("checkForUpdatesInterval") ObjectBinding<Duration> period) {
ScheduledService<String> service = new ScheduledService<>() {
@Override
protected Task<String> createTask() {
return new UpdateCheckerTask(httpClient, checkForUpdatesRequest);
if (httpClient.isPresent()) {
return new UpdateCheckerTask(httpClient.get(), checkForUpdatesRequest);
} else {
return new Task<>() {
@Override
protected String call() {
throw new NullPointerException("No HttpClient present.");
}
};
}
}
};
service.setOnFailed(event -> LOG.error("Failed to execute update service", service.getException()));
@@ -1,5 +1,6 @@
package org.cryptomator.ui.launcher;
import org.cryptomator.common.vaults.Vault;
import org.cryptomator.common.vaults.VaultListManager;
import org.cryptomator.ui.fxapp.FxApplication;
import org.slf4j.Logger;
@@ -55,7 +56,7 @@ class AppLaunchEventHandler {
case REVEAL_APP -> fxApplicationStarter.get().thenAccept(FxApplication::showMainWindow);
case OPEN_FILE -> fxApplicationStarter.get().thenRun(() -> {
Platform.runLater(() -> {
event.getPathsToOpen().forEach(this::addVault);
event.getPathsToOpen().forEach(this::addOrRevealVault);
});
});
default -> LOG.warn("Unsupported event type: {}", event.getType());
@@ -63,13 +64,18 @@ class AppLaunchEventHandler {
}
// TODO dedup MainWindowController...
private void addVault(Path potentialVaultPath) {
private void addOrRevealVault(Path potentialVaultPath) {
assert Platform.isFxApplicationThread();
try {
final Vault v;
if (potentialVaultPath.getFileName().toString().equals(MASTERKEY_FILENAME)) {
vaultListManager.add(potentialVaultPath.getParent());
v = vaultListManager.add(potentialVaultPath.getParent());
} else {
vaultListManager.add(potentialVaultPath);
v = vaultListManager.add(potentialVaultPath);
}
if (v.isUnlocked()) {
fxApplicationStarter.get().thenAccept(app -> app.getVaultService().reveal(v));
}
LOG.debug("Added vault {}", potentialVaultPath);
} catch (NoSuchFileException e) {
@@ -6,7 +6,7 @@ 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.FxmlLoaderFactory;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.common.FxControllerKey;
import org.cryptomator.ui.common.FxmlFile;
@@ -40,8 +40,8 @@ abstract class LockModule {
@Provides
@LockWindow
@LockScoped
static FXMLLoaderFactory provideFxmlLoaderFactory(Map<Class<? extends FxController>, Provider<FxController>> factories, DefaultSceneFactory sceneFactory, ResourceBundle resourceBundle) {
return new FXMLLoaderFactory(factories, sceneFactory, resourceBundle);
static FxmlLoaderFactory provideFxmlLoaderFactory(Map<Class<? extends FxController>, Provider<FxController>> factories, DefaultSceneFactory sceneFactory, ResourceBundle resourceBundle) {
return new FxmlLoaderFactory(factories, sceneFactory, resourceBundle);
}
@Provides
@@ -63,15 +63,15 @@ abstract class LockModule {
@Provides
@FxmlScene(FxmlFile.LOCK_FORCED)
@LockScoped
static Scene provideForceLockScene(@LockWindow FXMLLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene("/fxml/lock_forced.fxml");
static Scene provideForceLockScene(@LockWindow FxmlLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene(FxmlFile.LOCK_FORCED);
}
@Provides
@FxmlScene(FxmlFile.LOCK_FAILED)
@LockScoped
static Scene provideLockFailedScene(@LockWindow FXMLLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene("/fxml/lock_failed.fxml");
static Scene provideLockFailedScene(@LockWindow FxmlLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene(FxmlFile.LOCK_FAILED);
}
// ------------------
@@ -6,7 +6,7 @@ import dagger.Provides;
import dagger.multibindings.IntoMap;
import org.cryptomator.common.vaults.Vault;
import org.cryptomator.ui.addvaultwizard.AddVaultWizardComponent;
import org.cryptomator.ui.common.FXMLLoaderFactory;
import org.cryptomator.ui.common.FxmlLoaderFactory;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.common.FxControllerKey;
import org.cryptomator.ui.common.FxmlFile;
@@ -39,8 +39,8 @@ abstract class MainWindowModule {
@Provides
@MainWindow
@MainWindowScoped
static FXMLLoaderFactory provideFxmlLoaderFactory(Map<Class<? extends FxController>, Provider<FxController>> factories, MainWindowSceneFactory sceneFactory, ResourceBundle resourceBundle) {
return new FXMLLoaderFactory(factories, sceneFactory, resourceBundle);
static FxmlLoaderFactory provideFxmlLoaderFactory(Map<Class<? extends FxController>, Provider<FxController>> factories, MainWindowSceneFactory sceneFactory, ResourceBundle resourceBundle) {
return new FxmlLoaderFactory(factories, sceneFactory, resourceBundle);
}
@Provides
@@ -60,8 +60,8 @@ abstract class MainWindowModule {
@Provides
@FxmlScene(FxmlFile.MAIN_WINDOW)
@MainWindowScoped
static Scene provideMainScene(@MainWindow FXMLLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene("/fxml/main_window.fxml");
static Scene provideMainScene(@MainWindow FxmlLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene(FxmlFile.MAIN_WINDOW);
}
// ------------------
@@ -86,6 +86,11 @@ abstract class MainWindowModule {
@FxControllerKey(VaultListController.class)
abstract FxController bindVaultListController(VaultListController controller);
@Binds
@IntoMap
@FxControllerKey(VaultListContextMenuController.class)
abstract FxController bindVaultListContextMenuController(VaultListContextMenuController controller);
@Binds
@IntoMap
@FxControllerKey(VaultDetailController.class)
@@ -5,6 +5,7 @@ import org.cryptomator.common.keychain.KeychainManager;
import org.cryptomator.common.vaults.Vault;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.fxapp.FxApplication;
import org.cryptomator.ui.vaultoptions.SelectedVaultOptionsTab;
import org.cryptomator.ui.vaultoptions.VaultOptionsComponent;
import javax.inject.Inject;
@@ -47,7 +48,12 @@ public class VaultDetailLockedController implements FxController {
@FXML
public void showVaultOptions() {
vaultOptionsWindow.vault(vault.get()).build().showVaultOptionsWindow();
vaultOptionsWindow.vault(vault.get()).build().showVaultOptionsWindow(SelectedVaultOptionsTab.ANY);
}
@FXML
public void showKeyVaultOptions() {
vaultOptionsWindow.vault(vault.get()).build().showVaultOptionsWindow(SelectedVaultOptionsTab.KEY);
}
/* Getter/Setter */
@@ -1,7 +1,7 @@
package org.cryptomator.ui.mainwindow;
import org.cryptomator.common.vaults.Vault;
import org.cryptomator.ui.common.FXMLLoaderFactory;
import org.cryptomator.ui.common.FxmlLoaderFactory;
import org.cryptomator.ui.controls.DraggableListCell;
import javax.inject.Inject;
@@ -17,10 +17,10 @@ import java.io.UncheckedIOException;
@MainWindowScoped
public class VaultListCellFactory implements Callback<ListView<Vault>, ListCell<Vault>> {
private final FXMLLoaderFactory fxmlLoaders;
private final FxmlLoaderFactory fxmlLoaders;
@Inject
VaultListCellFactory(@MainWindow FXMLLoaderFactory fxmlLoaders) {
VaultListCellFactory(@MainWindow FxmlLoaderFactory fxmlLoaders) {
this.fxmlLoaders = fxmlLoaders;
}
@@ -0,0 +1,135 @@
package org.cryptomator.ui.mainwindow;
import com.tobiasdiez.easybind.EasyBind;
import com.tobiasdiez.easybind.optional.ObservableOptionalValue;
import com.tobiasdiez.easybind.optional.OptionalBinding;
import org.cryptomator.common.keychain.KeychainManager;
import org.cryptomator.common.vaults.Vault;
import org.cryptomator.common.vaults.VaultState;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.fxapp.FxApplication;
import org.cryptomator.ui.removevault.RemoveVaultComponent;
import org.cryptomator.ui.vaultoptions.SelectedVaultOptionsTab;
import org.cryptomator.ui.vaultoptions.VaultOptionsComponent;
import javax.inject.Inject;
import javafx.beans.binding.Binding;
import javafx.beans.binding.Bindings;
import javafx.beans.property.ObjectProperty;
import javafx.fxml.FXML;
import javafx.stage.Stage;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.Optional;
import static org.cryptomator.common.vaults.VaultState.ERROR;
import static org.cryptomator.common.vaults.VaultState.LOCKED;
import static org.cryptomator.common.vaults.VaultState.MISSING;
import static org.cryptomator.common.vaults.VaultState.NEEDS_MIGRATION;
import static org.cryptomator.common.vaults.VaultState.UNLOCKED;
@MainWindowScoped
public class VaultListContextMenuController implements FxController {
private final ObservableOptionalValue<Vault> selectedVault;
private final Stage mainWindow;
private final FxApplication application;
private final KeychainManager keychain;
private final RemoveVaultComponent.Builder removeVault;
private final VaultOptionsComponent.Builder vaultOptionsWindow;
private final OptionalBinding<VaultState> selectedVaultState;
private final Binding<Boolean> selectedVaultPassphraseStored;
private final Binding<Boolean> selectedVaultRemovable;
private final Binding<Boolean> selectedVaultUnlockable;
private final Binding<Boolean> selectedVaultLockable;
@Inject
VaultListContextMenuController(ObjectProperty<Vault> selectedVault, @MainWindow Stage mainWindow, FxApplication application, KeychainManager keychain, RemoveVaultComponent.Builder removeVault, VaultOptionsComponent.Builder vaultOptionsWindow) {
this.selectedVault = EasyBind.wrapNullable(selectedVault);
this.mainWindow = mainWindow;
this.application = application;
this.keychain = keychain;
this.removeVault = removeVault;
this.vaultOptionsWindow = vaultOptionsWindow;
this.selectedVaultState = this.selectedVault.mapObservable(Vault::stateProperty);
this.selectedVaultPassphraseStored = this.selectedVault.map(this::isPasswordStored).orElse(false);
this.selectedVaultRemovable = selectedVaultState.map(EnumSet.of(LOCKED, MISSING, ERROR, NEEDS_MIGRATION)::contains).orElse(false);
this.selectedVaultUnlockable = selectedVaultState.map(LOCKED::equals).orElse(false);
this.selectedVaultLockable = selectedVaultState.map(UNLOCKED::equals).orElse(false);
}
private boolean isPasswordStored(Vault vault) {
return keychain.getPassphraseStoredProperty(vault.getId()).get();
}
@FXML
public void didClickRemoveVault() {
selectedVault.ifValuePresent(v -> {
removeVault.vault(v).build().showRemoveVault();
});
}
@FXML
public void didClickShowVaultOptions() {
selectedVault.ifValuePresent(v -> {
vaultOptionsWindow.vault(v).build().showVaultOptionsWindow(SelectedVaultOptionsTab.ANY);
});
}
@FXML
public void didClickUnlockVault() {
selectedVault.ifValuePresent(v -> {
application.startUnlockWorkflow(v, Optional.of(mainWindow));
});
}
@FXML
public void didClickLockVault() {
selectedVault.ifValuePresent(v -> {
application.startLockWorkflow(v, Optional.of(mainWindow));
});
}
@FXML
public void didClickRevealVault() {
selectedVault.ifValuePresent(v -> {
application.getVaultService().reveal(v);
});
}
// Getter and Setter
public Binding<Boolean> selectedVaultUnlockableProperty() {
return selectedVaultUnlockable;
}
public boolean isSelectedVaultUnlockable() {
return selectedVaultUnlockable.getValue();
}
public Binding<Boolean> selectedVaultLockableProperty() {
return selectedVaultLockable;
}
public boolean isSelectedVaultLockable() {
return selectedVaultLockable.getValue();
}
public Binding<Boolean> selectedVaultRemovableProperty() {
return selectedVaultRemovable;
}
public boolean isSelectedVaultRemovable() {
return selectedVaultRemovable.getValue();
}
public Binding<Boolean> selectedVaultPassphraseStoredProperty() {
return selectedVaultPassphraseStored;
}
public boolean isSelectedVaultPassphraseStored() {
return selectedVaultPassphraseStored.getValue();
}
}
@@ -4,9 +4,6 @@ import org.cryptomator.common.vaults.Vault;
import org.cryptomator.common.vaults.VaultListManager;
import org.cryptomator.ui.addvaultwizard.AddVaultWizardComponent;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.removevault.RemoveVaultComponent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import javafx.beans.binding.Bindings;
@@ -17,30 +14,30 @@ import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.scene.control.ListView;
import javafx.scene.input.ContextMenuEvent;
import javafx.scene.input.MouseEvent;
@MainWindowScoped
public class VaultListController implements FxController {
private static final Logger LOG = LoggerFactory.getLogger(VaultListController.class);
private final ObservableList<Vault> vaults;
private final ObjectProperty<Vault> selectedVault;
private final VaultListCellFactory cellFactory;
private final AddVaultWizardComponent.Builder addVaultWizard;
private final RemoveVaultComponent.Builder removeVault;
private final BooleanBinding noVaultSelected;
private final BooleanBinding emptyVaultList;
public ListView<Vault> vaultList;
@Inject
VaultListController(ObservableList<Vault> vaults, ObjectProperty<Vault> selectedVault, VaultListCellFactory cellFactory, AddVaultWizardComponent.Builder addVaultWizard, RemoveVaultComponent.Builder removeVault) {
VaultListController(ObservableList<Vault> vaults, ObjectProperty<Vault> selectedVault, VaultListCellFactory cellFactory, AddVaultWizardComponent.Builder addVaultWizard) {
this.vaults = vaults;
this.selectedVault = selectedVault;
this.cellFactory = cellFactory;
this.addVaultWizard = addVaultWizard;
this.removeVault = removeVault;
this.noVaultSelected = selectedVault.isNull();
this.emptyVaultList = Bindings.isEmpty(vaults);
selectedVault.addListener(this::selectedVaultDidChange);
}
@@ -56,6 +53,19 @@ public class VaultListController implements FxController {
}
}
});
vaultList.addEventFilter(MouseEvent.MOUSE_RELEASED, this::deselect);
vaultList.addEventFilter(ContextMenuEvent.CONTEXT_MENU_REQUESTED, request -> {
if (selectedVault.get() == null) {
request.consume();
}
});
}
private void deselect(MouseEvent released) {
if (released.getY() > (vaultList.getItems().size() * vaultList.fixedCellSizeProperty().get())) {
vaultList.getSelectionModel().clearSelection();
released.consume();
}
}
private void selectedVaultDidChange(@SuppressWarnings("unused") ObservableValue<? extends Vault> observableValue, @SuppressWarnings("unused") Vault oldValue, Vault newValue) {
@@ -70,16 +80,6 @@ public class VaultListController implements FxController {
addVaultWizard.build().showAddVaultWizard();
}
@FXML
public void didClickRemoveVault() {
Vault v = selectedVault.get();
if (v != null) {
removeVault.vault(v).build().showRemoveVault();
} else {
LOG.debug("Cannot remove a vault if none is selected.");
}
}
// Getter and Setter
public BooleanBinding emptyVaultListProperty() {
@@ -90,11 +90,4 @@ public class VaultListController implements FxController {
return emptyVaultList.get();
}
public BooleanBinding noVaultSelectedProperty() {
return noVaultSelected;
}
public boolean isNoVaultSelected() {
return noVaultSelected.get();
}
}
@@ -6,7 +6,7 @@ import dagger.Provides;
import dagger.multibindings.IntoMap;
import org.cryptomator.cryptofs.common.FileSystemCapabilityChecker;
import org.cryptomator.ui.common.DefaultSceneFactory;
import org.cryptomator.ui.common.FXMLLoaderFactory;
import org.cryptomator.ui.common.FxmlLoaderFactory;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.common.FxControllerKey;
import org.cryptomator.ui.common.FxmlFile;
@@ -30,8 +30,8 @@ abstract class MigrationModule {
@Provides
@MigrationWindow
@MigrationScoped
static FXMLLoaderFactory provideFxmlLoaderFactory(Map<Class<? extends FxController>, Provider<FxController>> factories, DefaultSceneFactory sceneFactory, ResourceBundle resourceBundle) {
return new FXMLLoaderFactory(factories, sceneFactory, resourceBundle);
static FxmlLoaderFactory provideFxmlLoaderFactory(Map<Class<? extends FxController>, Provider<FxController>> factories, DefaultSceneFactory sceneFactory, ResourceBundle resourceBundle) {
return new FxmlLoaderFactory(factories, sceneFactory, resourceBundle);
}
@Provides
@@ -56,36 +56,36 @@ abstract class MigrationModule {
@Provides
@FxmlScene(FxmlFile.MIGRATION_START)
@MigrationScoped
static Scene provideMigrationStartScene(@MigrationWindow FXMLLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene("/fxml/migration_start.fxml");
static Scene provideMigrationStartScene(@MigrationWindow FxmlLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene(FxmlFile.MIGRATION_START);
}
@Provides
@FxmlScene(FxmlFile.MIGRATION_RUN)
@MigrationScoped
static Scene provideMigrationRunScene(@MigrationWindow FXMLLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene("/fxml/migration_run.fxml");
static Scene provideMigrationRunScene(@MigrationWindow FxmlLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene(FxmlFile.MIGRATION_RUN);
}
@Provides
@FxmlScene(FxmlFile.MIGRATION_SUCCESS)
@MigrationScoped
static Scene provideMigrationSuccessScene(@MigrationWindow FXMLLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene("/fxml/migration_success.fxml");
static Scene provideMigrationSuccessScene(@MigrationWindow FxmlLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene(FxmlFile.MIGRATION_SUCCESS);
}
@Provides
@FxmlScene(FxmlFile.MIGRATION_CAPABILITY_ERROR)
@MigrationScoped
static Scene provideMigrationCapabilityErrorScene(@MigrationWindow FXMLLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene("/fxml/migration_capability_error.fxml");
static Scene provideMigrationCapabilityErrorScene(@MigrationWindow FxmlLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene(FxmlFile.MIGRATION_CAPABILITY_ERROR);
}
@Provides
@FxmlScene(FxmlFile.MIGRATION_IMPOSSIBLE)
@MigrationScoped
static Scene provideMigrationImpossibleScene(@MigrationWindow FXMLLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene("/fxml/migration_impossible.fxml");
static Scene provideMigrationImpossibleScene(@MigrationWindow FxmlLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene(FxmlFile.MIGRATION_IMPOSSIBLE);
}
// ------------------
@@ -12,7 +12,7 @@ import org.cryptomator.cryptofs.migration.api.MigrationProgressListener;
import org.cryptomator.cryptolib.api.InvalidPassphraseException;
import org.cryptomator.integrations.keychain.KeychainAccessException;
import org.cryptomator.ui.common.Animations;
import org.cryptomator.ui.common.ErrorComponent;
import org.cryptomator.ui.error.GenericErrorComponent;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.common.FxmlFile;
import org.cryptomator.ui.common.FxmlScene;
@@ -56,7 +56,7 @@ public class MigrationRunController implements FxController {
private final ScheduledExecutorService scheduler;
private final KeychainManager keychain;
private final ObjectProperty<FileSystemCapabilityChecker.Capability> missingCapability;
private final ErrorComponent.Builder errorComponent;
private final GenericErrorComponent.Builder genericErrorBuilder;
private final Lazy<Scene> startScene;
private final Lazy<Scene> successScene;
private final Lazy<Scene> impossibleScene;
@@ -68,14 +68,14 @@ public class MigrationRunController implements FxController {
public NiceSecurePasswordField passwordField;
@Inject
public MigrationRunController(@MigrationWindow Stage window, @MigrationWindow Vault vault, ExecutorService executor, ScheduledExecutorService scheduler, KeychainManager keychain, @Named("capabilityErrorCause") ObjectProperty<FileSystemCapabilityChecker.Capability> missingCapability, @FxmlScene(FxmlFile.MIGRATION_START) Lazy<Scene> startScene, @FxmlScene(FxmlFile.MIGRATION_SUCCESS) Lazy<Scene> successScene, @FxmlScene(FxmlFile.MIGRATION_CAPABILITY_ERROR) Lazy<Scene> capabilityErrorScene, @FxmlScene(FxmlFile.MIGRATION_IMPOSSIBLE) Lazy<Scene> impossibleScene, ErrorComponent.Builder errorComponent) {
public MigrationRunController(@MigrationWindow Stage window, @MigrationWindow Vault vault, ExecutorService executor, ScheduledExecutorService scheduler, KeychainManager keychain, @Named("capabilityErrorCause") ObjectProperty<FileSystemCapabilityChecker.Capability> missingCapability, @FxmlScene(FxmlFile.MIGRATION_START) Lazy<Scene> startScene, @FxmlScene(FxmlFile.MIGRATION_SUCCESS) Lazy<Scene> successScene, @FxmlScene(FxmlFile.MIGRATION_CAPABILITY_ERROR) Lazy<Scene> capabilityErrorScene, @FxmlScene(FxmlFile.MIGRATION_IMPOSSIBLE) Lazy<Scene> impossibleScene, GenericErrorComponent.Builder genericErrorBuilder) {
this.window = window;
this.vault = vault;
this.executor = executor;
this.scheduler = scheduler;
this.keychain = keychain;
this.missingCapability = missingCapability;
this.errorComponent = errorComponent;
this.genericErrorBuilder = genericErrorBuilder;
this.startScene = startScene;
this.successScene = successScene;
this.migrateButtonContentDisplay = Bindings.createObjectBinding(this::getMigrateButtonContentDisplay, vault.stateProperty());
@@ -136,12 +136,12 @@ public class MigrationRunController implements FxController {
}).onError(FileNameTooLongException.class, e -> {
LOG.error("Migration failed because the underlying file system does not support long filenames.", e);
vault.setState(VaultState.NEEDS_MIGRATION);
errorComponent.cause(e).window(window).returnToScene(startScene.get()).build().showErrorScene();
genericErrorBuilder.cause(e).window(window).returnToScene(startScene.get()).build().showErrorScene();
window.setScene(impossibleScene.get());
}).onError(Exception.class, e -> { // including RuntimeExceptions
LOG.error("Migration failed for technical reasons.", e);
vault.setState(VaultState.NEEDS_MIGRATION);
errorComponent.cause(e).window(window).returnToScene(startScene.get()).build().showErrorScene();
genericErrorBuilder.cause(e).window(window).returnToScene(startScene.get()).build().showErrorScene();
}).andFinally(() -> {
passwordField.setDisable(false);
progressSyncTask.cancel(true);
@@ -8,7 +8,7 @@ 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.error.GenericErrorComponent;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.traymenu.TrayMenuComponent;
import org.slf4j.Logger;
@@ -49,7 +49,7 @@ public class GeneralPreferencesController implements FxController {
private final Application application;
private final Environment environment;
private final Set<KeychainAccessProvider> keychainAccessProviders;
private final ErrorComponent.Builder errorComponent;
private final GenericErrorComponent.Builder genericErrorBuilder;
public ChoiceBox<UiTheme> themeChoiceBox;
public ChoiceBox<KeychainBackend> keychainBackendChoiceBox;
public CheckBox showMinimizeButtonCheckbox;
@@ -63,7 +63,7 @@ public class GeneralPreferencesController implements FxController {
@Inject
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) {
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, GenericErrorComponent.Builder genericErrorBuilder) {
this.window = window;
this.settings = settings;
this.trayMenuInitialized = trayMenu.isInitialized();
@@ -75,7 +75,7 @@ public class GeneralPreferencesController implements FxController {
this.resourceBundle = resourceBundle;
this.application = application;
this.environment = environment;
this.errorComponent = errorComponent;
this.genericErrorBuilder = genericErrorBuilder;
}
@FXML
@@ -146,7 +146,7 @@ public class GeneralPreferencesController implements FxController {
} catch (ToggleAutoStartFailedException e) {
autoStartCheckbox.setSelected(!enableAutoStart); // restore previous state
LOG.error("Failed to toggle autostart.", e);
errorComponent.cause(e).window(window).returnToScene(window.getScene()).build().showErrorScene();
genericErrorBuilder.cause(e).window(window).returnToScene(window.getScene()).build().showErrorScene();
}
});
}
@@ -5,7 +5,7 @@ import dagger.Module;
import dagger.Provides;
import dagger.multibindings.IntoMap;
import org.cryptomator.ui.common.DefaultSceneFactory;
import org.cryptomator.ui.common.FXMLLoaderFactory;
import org.cryptomator.ui.common.FxmlLoaderFactory;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.common.FxControllerKey;
import org.cryptomator.ui.common.FxmlFile;
@@ -32,8 +32,8 @@ abstract class PreferencesModule {
@Provides
@PreferencesWindow
@PreferencesScoped
static FXMLLoaderFactory provideFxmlLoaderFactory(Map<Class<? extends FxController>, Provider<FxController>> factories, DefaultSceneFactory sceneFactory, ResourceBundle resourceBundle) {
return new FXMLLoaderFactory(factories, sceneFactory, resourceBundle);
static FxmlLoaderFactory provideFxmlLoaderFactory(Map<Class<? extends FxController>, Provider<FxController>> factories, DefaultSceneFactory sceneFactory, ResourceBundle resourceBundle) {
return new FxmlLoaderFactory(factories, sceneFactory, resourceBundle);
}
@Provides
@@ -49,8 +49,8 @@ abstract class PreferencesModule {
@Provides
@FxmlScene(FxmlFile.PREFERENCES)
@PreferencesScoped
static Scene providePreferencesScene(@PreferencesWindow FXMLLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene("/fxml/preferences.fxml");
static Scene providePreferencesScene(@PreferencesWindow FxmlLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene(FxmlFile.PREFERENCES);
}
// ------------------
@@ -5,7 +5,7 @@ import dagger.Module;
import dagger.Provides;
import dagger.multibindings.IntoMap;
import org.cryptomator.ui.common.DefaultSceneFactory;
import org.cryptomator.ui.common.FXMLLoaderFactory;
import org.cryptomator.ui.common.FxmlLoaderFactory;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.common.FxControllerKey;
import org.cryptomator.ui.common.FxmlFile;
@@ -25,8 +25,8 @@ abstract class QuitModule {
@Provides
@QuitWindow
@QuitScoped
static FXMLLoaderFactory provideFxmlLoaderFactory(Map<Class<? extends FxController>, Provider<FxController>> factories, DefaultSceneFactory sceneFactory, ResourceBundle resourceBundle) {
return new FXMLLoaderFactory(factories, sceneFactory, resourceBundle);
static FxmlLoaderFactory provideFxmlLoaderFactory(Map<Class<? extends FxController>, Provider<FxController>> factories, DefaultSceneFactory sceneFactory, ResourceBundle resourceBundle) {
return new FxmlLoaderFactory(factories, sceneFactory, resourceBundle);
}
@Provides
@@ -43,8 +43,8 @@ abstract class QuitModule {
@Provides
@FxmlScene(FxmlFile.QUIT)
@QuitScoped
static Scene provideQuitScene(@QuitWindow FXMLLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene("/fxml/quit.fxml");
static Scene provideQuitScene(@QuitWindow FxmlLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene(FxmlFile.QUIT);
}
// ------------------
@@ -4,7 +4,7 @@ import dagger.Lazy;
import org.cryptomator.common.vaults.Vault;
import org.cryptomator.cryptolib.api.InvalidPassphraseException;
import org.cryptomator.ui.common.Animations;
import org.cryptomator.ui.common.ErrorComponent;
import org.cryptomator.ui.error.GenericErrorComponent;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.common.FxmlFile;
import org.cryptomator.ui.common.FxmlScene;
@@ -32,18 +32,18 @@ public class RecoveryKeyCreationController implements FxController {
private final ExecutorService executor;
private final RecoveryKeyFactory recoveryKeyFactory;
private final StringProperty recoveryKeyProperty;
private final ErrorComponent.Builder errorComponent;
private final GenericErrorComponent.Builder genericErrorBuilder;
public NiceSecurePasswordField passwordField;
@Inject
public RecoveryKeyCreationController(@RecoveryKeyWindow Stage window, @FxmlScene(FxmlFile.RECOVERYKEY_SUCCESS) Lazy<Scene> successScene, @RecoveryKeyWindow Vault vault, RecoveryKeyFactory recoveryKeyFactory, ExecutorService executor, @RecoveryKeyWindow StringProperty recoveryKey, ErrorComponent.Builder errorComponent) {
public RecoveryKeyCreationController(@RecoveryKeyWindow Stage window, @FxmlScene(FxmlFile.RECOVERYKEY_SUCCESS) Lazy<Scene> successScene, @RecoveryKeyWindow Vault vault, RecoveryKeyFactory recoveryKeyFactory, ExecutorService executor, @RecoveryKeyWindow StringProperty recoveryKey, GenericErrorComponent.Builder genericErrorBuilder) {
this.window = window;
this.successScene = successScene;
this.vault = vault;
this.executor = executor;
this.recoveryKeyFactory = recoveryKeyFactory;
this.recoveryKeyProperty = recoveryKey;
this.errorComponent = errorComponent;
this.genericErrorBuilder = genericErrorBuilder;
}
@FXML
@@ -62,7 +62,7 @@ public class RecoveryKeyCreationController implements FxController {
Animations.createShakeWindowAnimation(window).play();
} else {
LOG.error("Creation of recovery key failed.", task.getException());
errorComponent.cause(task.getException()).window(window).returnToScene(window.getScene()).build().showErrorScene();
genericErrorBuilder.cause(task.getException()).window(window).returnToScene(window.getScene()).build().showErrorScene();
}
});
executor.submit(task);
@@ -6,7 +6,7 @@ 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.FxmlLoaderFactory;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.common.FxControllerKey;
import org.cryptomator.ui.common.FxmlFile;
@@ -33,8 +33,8 @@ abstract class RecoveryKeyModule {
@Provides
@RecoveryKeyWindow
@RecoveryKeyScoped
static FXMLLoaderFactory provideFxmlLoaderFactory(Map<Class<? extends FxController>, Provider<FxController>> factories, DefaultSceneFactory sceneFactory, ResourceBundle resourceBundle) {
return new FXMLLoaderFactory(factories, sceneFactory, resourceBundle);
static FxmlLoaderFactory provideFxmlLoaderFactory(Map<Class<? extends FxController>, Provider<FxController>> factories, DefaultSceneFactory sceneFactory, ResourceBundle resourceBundle) {
return new FxmlLoaderFactory(factories, sceneFactory, resourceBundle);
}
@Provides
@@ -69,29 +69,29 @@ abstract class RecoveryKeyModule {
@Provides
@FxmlScene(FxmlFile.RECOVERYKEY_CREATE)
@RecoveryKeyScoped
static Scene provideRecoveryKeyCreationScene(@RecoveryKeyWindow FXMLLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene("/fxml/recoverykey_create.fxml");
static Scene provideRecoveryKeyCreationScene(@RecoveryKeyWindow FxmlLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene(FxmlFile.RECOVERYKEY_CREATE);
}
@Provides
@FxmlScene(FxmlFile.RECOVERYKEY_SUCCESS)
@RecoveryKeyScoped
static Scene provideRecoveryKeySuccessScene(@RecoveryKeyWindow FXMLLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene("/fxml/recoverykey_success.fxml");
static Scene provideRecoveryKeySuccessScene(@RecoveryKeyWindow FxmlLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene(FxmlFile.RECOVERYKEY_SUCCESS);
}
@Provides
@FxmlScene(FxmlFile.RECOVERYKEY_RECOVER)
@RecoveryKeyScoped
static Scene provideRecoveryKeyRecoverScene(@RecoveryKeyWindow FXMLLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene("/fxml/recoverykey_recover.fxml");
static Scene provideRecoveryKeyRecoverScene(@RecoveryKeyWindow FxmlLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene(FxmlFile.RECOVERYKEY_RECOVER);
}
@Provides
@FxmlScene(FxmlFile.RECOVERYKEY_RESET_PASSWORD)
@RecoveryKeyScoped
static Scene provideRecoveryKeyResetPasswordScene(@RecoveryKeyWindow FXMLLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene("/fxml/recoverykey_reset_password.fxml");
static Scene provideRecoveryKeyResetPasswordScene(@RecoveryKeyWindow FxmlLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene(FxmlFile.RECOVERYKEY_RESET_PASSWORD);
}
// ------------------
@@ -2,7 +2,7 @@ package org.cryptomator.ui.recoverykey;
import dagger.Lazy;
import org.cryptomator.common.vaults.Vault;
import org.cryptomator.ui.common.ErrorComponent;
import org.cryptomator.ui.error.GenericErrorComponent;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.common.FxmlFile;
import org.cryptomator.ui.common.FxmlScene;
@@ -35,10 +35,10 @@ public class RecoveryKeyResetPasswordController implements FxController {
private final ObjectProperty<CharSequence> newPassword;
private final Lazy<Scene> recoverScene;
private final BooleanBinding invalidNewPassword;
private final ErrorComponent.Builder errorComponent;
private final GenericErrorComponent.Builder genericErrorBuilder;
@Inject
public RecoveryKeyResetPasswordController(@RecoveryKeyWindow Stage window, @RecoveryKeyWindow Vault vault, RecoveryKeyFactory recoveryKeyFactory, ExecutorService executor, @RecoveryKeyWindow StringProperty recoveryKey, @Named("newPassword") ObjectProperty<CharSequence> newPassword, @FxmlScene(FxmlFile.RECOVERYKEY_RECOVER) Lazy<Scene> recoverScene, ErrorComponent.Builder errorComponent) {
public RecoveryKeyResetPasswordController(@RecoveryKeyWindow Stage window, @RecoveryKeyWindow Vault vault, RecoveryKeyFactory recoveryKeyFactory, ExecutorService executor, @RecoveryKeyWindow StringProperty recoveryKey, @Named("newPassword") ObjectProperty<CharSequence> newPassword, @FxmlScene(FxmlFile.RECOVERYKEY_RECOVER) Lazy<Scene> recoverScene, GenericErrorComponent.Builder genericErrorBuilder) {
this.window = window;
this.vault = vault;
this.recoveryKeyFactory = recoveryKeyFactory;
@@ -47,7 +47,7 @@ public class RecoveryKeyResetPasswordController implements FxController {
this.newPassword = newPassword;
this.recoverScene = recoverScene;
this.invalidNewPassword = Bindings.createBooleanBinding(this::isInvalidNewPassword, newPassword);
this.errorComponent = errorComponent;
this.genericErrorBuilder = genericErrorBuilder;
}
@FXML
@@ -68,7 +68,7 @@ public class RecoveryKeyResetPasswordController implements FxController {
});
task.setOnFailed(event -> {
LOG.error("Resetting password failed.", task.getException());
errorComponent.cause(task.getException()).window(window).returnToScene(recoverScene.get()).build().showErrorScene();
genericErrorBuilder.cause(task.getException()).window(window).returnToScene(recoverScene.get()).build().showErrorScene();
});
executor.submit(task);
}
@@ -5,7 +5,7 @@ import dagger.Module;
import dagger.Provides;
import dagger.multibindings.IntoMap;
import org.cryptomator.ui.common.DefaultSceneFactory;
import org.cryptomator.ui.common.FXMLLoaderFactory;
import org.cryptomator.ui.common.FxmlLoaderFactory;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.common.FxControllerKey;
import org.cryptomator.ui.common.FxmlFile;
@@ -26,8 +26,8 @@ abstract class RemoveVaultModule {
@Provides
@RemoveVaultWindow
@RemoveVaultScoped
static FXMLLoaderFactory provideFxmlLoaderFactory(Map<Class<? extends FxController>, Provider<FxController>> factories, DefaultSceneFactory sceneFactory, ResourceBundle resourceBundle) {
return new FXMLLoaderFactory(factories, sceneFactory, resourceBundle);
static FxmlLoaderFactory provideFxmlLoaderFactory(Map<Class<? extends FxController>, Provider<FxController>> factories, DefaultSceneFactory sceneFactory, ResourceBundle resourceBundle) {
return new FxmlLoaderFactory(factories, sceneFactory, resourceBundle);
}
@Provides
@@ -45,8 +45,8 @@ abstract class RemoveVaultModule {
@Provides
@FxmlScene(FxmlFile.REMOVE_VAULT)
@RemoveVaultScoped
static Scene provideRemoveVaultScene(@RemoveVaultWindow FXMLLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene("/fxml/remove_vault.fxml");
static Scene provideRemoveVaultScene(@RemoveVaultWindow FxmlLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene(FxmlFile.REMOVE_VAULT);
}
// ------------------
@@ -11,7 +11,7 @@ import javafx.stage.Stage;
import org.cryptomator.common.vaults.Vault;
import org.cryptomator.common.vaults.VaultState;
import org.cryptomator.ui.common.DefaultSceneFactory;
import org.cryptomator.ui.common.FXMLLoaderFactory;
import org.cryptomator.ui.common.FxmlLoaderFactory;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.common.FxControllerKey;
import org.cryptomator.ui.common.FxmlFile;
@@ -29,8 +29,8 @@ abstract class VaultStatisticsModule {
@Provides
@VaultStatisticsWindow
@VaultStatisticsScoped
static FXMLLoaderFactory provideFxmlLoaderFactory(Map<Class<? extends FxController>, Provider<FxController>> factories, DefaultSceneFactory sceneFactory, ResourceBundle resourceBundle) {
return new FXMLLoaderFactory(factories, sceneFactory, resourceBundle);
static FxmlLoaderFactory provideFxmlLoaderFactory(Map<Class<? extends FxController>, Provider<FxController>> factories, DefaultSceneFactory sceneFactory, ResourceBundle resourceBundle) {
return new FxmlLoaderFactory(factories, sceneFactory, resourceBundle);
}
@Provides
@@ -60,8 +60,8 @@ abstract class VaultStatisticsModule {
@Provides
@FxmlScene(FxmlFile.VAULT_STATISTICS)
@VaultStatisticsScoped
static Scene provideVaultStatisticsScene(@VaultStatisticsWindow FXMLLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene("/fxml/stats.fxml");
static Scene provideVaultStatisticsScene(@VaultStatisticsWindow FxmlLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene(FxmlFile.VAULT_STATISTICS);
}
// ------------------
@@ -1,49 +1,38 @@
package org.cryptomator.ui.unlock;
import dagger.Lazy;
import org.cryptomator.common.vaults.MountPointRequirement;
import org.cryptomator.common.vaults.Vault;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.common.FxmlFile;
import org.cryptomator.ui.common.FxmlScene;
import org.cryptomator.ui.error.AbstractErrorController;
import org.cryptomator.ui.error.ErrorReport;
import javax.annotation.Nullable;
import javax.inject.Inject;
import javafx.fxml.FXML;
import javafx.scene.Scene;
import javafx.stage.Stage;
//At the current point in time only the CustomMountPointChooser may cause this window to be shown.
@UnlockScoped
public class UnlockInvalidMountPointController implements FxController {
public class UnlockInvalidMountPointController extends AbstractErrorController {
private final Stage window;
private final Lazy<Scene> unlockScene;
private final Vault vault;
@Inject
UnlockInvalidMountPointController(@UnlockWindow Stage window, @FxmlScene(FxmlFile.UNLOCK) Lazy<Scene> unlockScene, @UnlockWindow Vault vault) {
this.window = window;
this.unlockScene = unlockScene;
UnlockInvalidMountPointController(@ErrorReport Stage window, @ErrorReport @Nullable Scene previousScene, @ErrorReport Vault vault) {
super(window, previousScene);
this.vault = vault;
}
@FXML
public void back() {
window.setScene(unlockScene.get());
}
/* Getter/Setter */
public String getMountPoint() {
return vault.getVaultSettings().getCustomMountPath().orElse("AUTO");
return this.vault.getVaultSettings().getCustomMountPath().orElse("AUTO");
}
public boolean getMustExist() {
MountPointRequirement requirement = vault.getVolume().orElseThrow(() -> new IllegalStateException("Invalid Mountpoint without a Volume?!")).getMountPointRequirement();
MountPointRequirement requirement = this.vault.getVolume().orElseThrow(() -> new IllegalStateException("Invalid Mountpoint without a Volume?!")).getMountPointRequirement();
assert requirement != MountPointRequirement.NONE; //An invalid MountPoint with no required MountPoint doesn't seem sensible
assert requirement != MountPointRequirement.PARENT_OPT_MOUNT_POINT; //Not implemented anywhere (yet)
return requirement == MountPointRequirement.EMPTY_MOUNT_POINT;
}
}
@@ -8,7 +8,7 @@ import org.cryptomator.common.keychain.KeychainManager;
import org.cryptomator.common.vaults.Vault;
import org.cryptomator.integrations.keychain.KeychainAccessException;
import org.cryptomator.ui.common.DefaultSceneFactory;
import org.cryptomator.ui.common.FXMLLoaderFactory;
import org.cryptomator.ui.common.FxmlLoaderFactory;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.common.FxControllerKey;
import org.cryptomator.ui.common.FxmlFile;
@@ -78,8 +78,8 @@ abstract class UnlockModule {
@Provides
@UnlockWindow
@UnlockScoped
static FXMLLoaderFactory provideFxmlLoaderFactory(Map<Class<? extends FxController>, Provider<FxController>> factories, DefaultSceneFactory sceneFactory, ResourceBundle resourceBundle) {
return new FXMLLoaderFactory(factories, sceneFactory, resourceBundle);
static FxmlLoaderFactory provideFxmlLoaderFactory(Map<Class<? extends FxController>, Provider<FxController>> factories, DefaultSceneFactory sceneFactory, ResourceBundle resourceBundle) {
return new FxmlLoaderFactory(factories, sceneFactory, resourceBundle);
}
@Provides
@@ -101,22 +101,22 @@ abstract class UnlockModule {
@Provides
@FxmlScene(FxmlFile.UNLOCK)
@UnlockScoped
static Scene provideUnlockScene(@UnlockWindow FXMLLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene("/fxml/unlock.fxml");
static Scene provideUnlockScene(@UnlockWindow FxmlLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene(FxmlFile.UNLOCK);
}
@Provides
@FxmlScene(FxmlFile.UNLOCK_SUCCESS)
@UnlockScoped
static Scene provideUnlockSuccessScene(@UnlockWindow FXMLLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene("/fxml/unlock_success.fxml");
static Scene provideUnlockSuccessScene(@UnlockWindow FxmlLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene(FxmlFile.UNLOCK_SUCCESS);
}
@Provides
@FxmlScene(FxmlFile.UNLOCK_INVALID_MOUNT_POINT)
@UnlockScoped
static Scene provideInvalidMountPointScene(@UnlockWindow FXMLLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene("/fxml/unlock_invalid_mount_point.fxml");
static Scene provideInvalidMountPointScene(@UnlockWindow FxmlLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene(FxmlFile.UNLOCK_INVALID_MOUNT_POINT);
}
// ------------------
@@ -130,10 +130,4 @@ abstract class UnlockModule {
@IntoMap
@FxControllerKey(UnlockSuccessController.class)
abstract FxController bindUnlockSuccessController(UnlockSuccessController controller);
@Binds
@IntoMap
@FxControllerKey(UnlockInvalidMountPointController.class)
abstract FxController bindUnlockInvalidMountPointController(UnlockInvalidMountPointController controller);
}
@@ -8,6 +8,6 @@ import java.lang.annotation.RetentionPolicy;
@Scope
@Documented
@Retention(RetentionPolicy.RUNTIME)
@interface UnlockScoped {
public @interface UnlockScoped {
}
@@ -10,11 +10,12 @@ import org.cryptomator.common.vaults.Volume.VolumeException;
import org.cryptomator.cryptolib.api.InvalidPassphraseException;
import org.cryptomator.integrations.keychain.KeychainAccessException;
import org.cryptomator.ui.common.Animations;
import org.cryptomator.ui.common.ErrorComponent;
import org.cryptomator.ui.common.FxmlFile;
import org.cryptomator.ui.common.FxmlScene;
import org.cryptomator.ui.common.UserInteractionLock;
import org.cryptomator.ui.common.VaultService;
import org.cryptomator.ui.error.GenericErrorComponent;
import org.cryptomator.ui.error.InvalidMountPointExceptionComponent;
import org.cryptomator.ui.unlock.UnlockModule.PasswordEntry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -56,11 +57,11 @@ public class UnlockWorkflow extends Task<Boolean> {
private final KeychainManager keychain;
private final Lazy<Scene> unlockScene;
private final Lazy<Scene> successScene;
private final Lazy<Scene> invalidMountPointScene;
private final ErrorComponent.Builder errorComponent;
private final GenericErrorComponent.Builder genericErrorBuilder;
private final InvalidMountPointExceptionComponent.Builder invalidMountPointExceptionBuilder;
@Inject
UnlockWorkflow(@UnlockWindow Stage window, @UnlockWindow Vault vault, VaultService vaultService, AtomicReference<char[]> password, @Named("savePassword") AtomicBoolean savePassword, @Named("savedPassword") Optional<char[]> savedPassword, UserInteractionLock<PasswordEntry> passwordEntryLock, KeychainManager keychain, @FxmlScene(FxmlFile.UNLOCK) Lazy<Scene> unlockScene, @FxmlScene(FxmlFile.UNLOCK_SUCCESS) Lazy<Scene> successScene, @FxmlScene(FxmlFile.UNLOCK_INVALID_MOUNT_POINT) Lazy<Scene> invalidMountPointScene, ErrorComponent.Builder errorComponent) {
UnlockWorkflow(@UnlockWindow Stage window, @UnlockWindow Vault vault, VaultService vaultService, AtomicReference<char[]> password, @Named("savePassword") AtomicBoolean savePassword, @Named("savedPassword") Optional<char[]> savedPassword, UserInteractionLock<PasswordEntry> passwordEntryLock, KeychainManager keychain, @FxmlScene(FxmlFile.UNLOCK) Lazy<Scene> unlockScene, @FxmlScene(FxmlFile.UNLOCK_SUCCESS) Lazy<Scene> successScene, GenericErrorComponent.Builder genericErrorBuilder, InvalidMountPointExceptionComponent.Builder invalidMountPointExceptionBuilder) {
this.window = window;
this.vault = vault;
this.vaultService = vaultService;
@@ -71,13 +72,13 @@ public class UnlockWorkflow extends Task<Boolean> {
this.keychain = keychain;
this.unlockScene = unlockScene;
this.successScene = successScene;
this.invalidMountPointScene = invalidMountPointScene;
this.errorComponent = errorComponent;
this.genericErrorBuilder = genericErrorBuilder;
this.invalidMountPointExceptionBuilder = invalidMountPointExceptionBuilder;
setOnFailed(event -> {
Throwable throwable = event.getSource().getException();
if (throwable instanceof InvalidMountPointException) {
handleInvalidMountPoint((InvalidMountPointException) throwable);
if (throwable instanceof InvalidMountPointException e) {
handleInvalidMountPoint(e);
} else {
handleGenericError(throwable);
}
@@ -172,31 +173,28 @@ public class UnlockWorkflow extends Task<Boolean> {
} else {
LOG.error("Unlock failed. Mountpoint doesn't exist (needs to be a folder): {}", cause.getMessage());
}
showInvalidMountPointScene();
showInvalidMountPointScene(cause);
return;
} else if (cause instanceof FileAlreadyExistsException) {
LOG.error("Unlock failed. Mountpoint already exists: {}", cause.getMessage());
showInvalidMountPointScene();
showInvalidMountPointScene(cause);
return;
} else if (cause instanceof DirectoryNotEmptyException) {
LOG.error("Unlock failed. Mountpoint not an empty directory: {}", cause.getMessage());
showInvalidMountPointScene();
showInvalidMountPointScene(cause);
return;
} else {
handleGenericError(impExc);
}
}
private void showInvalidMountPointScene() {
Platform.runLater(() -> {
window.setScene(invalidMountPointScene.get());
window.show();
});
private void showInvalidMountPointScene(Throwable e) {
invalidMountPointExceptionBuilder.cause(e).window(window).returnToScene(window.getScene()).vault(vault).build().showErrorScene();
}
private void handleGenericError(Throwable e) {
LOG.error("Unlock failed for technical reasons.", e);
errorComponent.cause(e).window(window).returnToScene(window.getScene()).build().showErrorScene();
genericErrorBuilder.cause(e).window(window).returnToScene(window.getScene()).build().showErrorScene();
}
private void wipePassword(char[] pw) {
@@ -0,0 +1,23 @@
package org.cryptomator.ui.vaultoptions;
public enum SelectedVaultOptionsTab {
/**
* Let the controller decide which tab to show.
*/
ANY,
/**
* Show general tab
*/
GENERAL,
/**
* Show mounting tab
*/
MOUNT,
/**
* Show password tab
*/
KEY,
}
@@ -12,6 +12,7 @@ import org.cryptomator.common.vaults.Vault;
import org.cryptomator.ui.common.FxmlFile;
import org.cryptomator.ui.common.FxmlScene;
import javafx.beans.property.ObjectProperty;
import javafx.scene.Scene;
import javafx.stage.Stage;
@@ -25,7 +26,10 @@ public interface VaultOptionsComponent {
@FxmlScene(FxmlFile.VAULT_OPTIONS)
Lazy<Scene> scene();
default void showVaultOptionsWindow() {
ObjectProperty<SelectedVaultOptionsTab> selectedTabProperty();
default void showVaultOptionsWindow(SelectedVaultOptionsTab selectedTab) {
selectedTabProperty().set(selectedTab);
Stage stage = window();
stage.setScene(scene().get());
stage.show();
@@ -1,13 +1,67 @@
package org.cryptomator.ui.vaultoptions;
import org.cryptomator.ui.common.FxController;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import javafx.beans.property.ObjectProperty;
import javafx.fxml.FXML;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
@VaultOptionsScoped
public class VaultOptionsController implements FxController {
private static final Logger LOG = LoggerFactory.getLogger(VaultOptionsController.class);
private final Stage window;
private final ObjectProperty<SelectedVaultOptionsTab> selectedTabProperty;
public TabPane tabPane;
public Tab generalTab;
public Tab mountTab;
public Tab keyTab;
@Inject
VaultOptionsController() {}
VaultOptionsController(@VaultOptionsWindow Stage window, ObjectProperty<SelectedVaultOptionsTab> selectedTabProperty) {
this.window = window;
this.selectedTabProperty = selectedTabProperty;
}
@FXML
public void initialize() {
window.setOnShowing(this::windowWillAppear);
selectedTabProperty.addListener(observable -> this.selectChosenTab());
tabPane.getSelectionModel().selectedItemProperty().addListener(observable -> this.selectedTabChanged());
}
private void selectChosenTab() {
Tab toBeSelected = getTabToSelect(selectedTabProperty.get());
tabPane.getSelectionModel().select(toBeSelected);
}
private Tab getTabToSelect(SelectedVaultOptionsTab selectedTab) {
return switch (selectedTab) {
case ANY, GENERAL -> generalTab;
case MOUNT -> mountTab;
case KEY -> keyTab;
};
}
private void selectedTabChanged() {
Tab selectedTab = tabPane.getSelectionModel().getSelectedItem();
try {
SelectedVaultOptionsTab selectedVaultOptionsTab = SelectedVaultOptionsTab.valueOf(selectedTab.getId());
selectedTabProperty.set(selectedVaultOptionsTab);
} catch (IllegalArgumentException e) {
LOG.error("Unknown vault options tab id: {}", selectedTab.getId());
}
}
private void windowWillAppear(@SuppressWarnings("unused") WindowEvent windowEvent) {
selectChosenTab();
}
}
@@ -7,16 +7,18 @@ import dagger.multibindings.IntoMap;
import org.cryptomator.common.vaults.Vault;
import org.cryptomator.ui.changepassword.ChangePasswordComponent;
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.FxmlLoaderFactory;
import org.cryptomator.ui.common.FxmlScene;
import org.cryptomator.ui.common.StageFactory;
import org.cryptomator.ui.mainwindow.MainWindow;
import org.cryptomator.ui.recoverykey.RecoveryKeyComponent;
import javax.inject.Provider;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.scene.Scene;
import javafx.stage.Modality;
import javafx.stage.Stage;
@@ -26,11 +28,17 @@ import java.util.ResourceBundle;
@Module(subcomponents = {ChangePasswordComponent.class, RecoveryKeyComponent.class})
abstract class VaultOptionsModule {
@Provides
@VaultOptionsScoped
static ObjectProperty<SelectedVaultOptionsTab> provideSelectedTabProperty() {
return new SimpleObjectProperty<>(SelectedVaultOptionsTab.ANY);
}
@Provides
@VaultOptionsWindow
@VaultOptionsScoped
static FXMLLoaderFactory provideFxmlLoaderFactory(Map<Class<? extends FxController>, Provider<FxController>> factories, DefaultSceneFactory sceneFactory, ResourceBundle resourceBundle) {
return new FXMLLoaderFactory(factories, sceneFactory, resourceBundle);
static FxmlLoaderFactory provideFxmlLoaderFactory(Map<Class<? extends FxController>, Provider<FxController>> factories, DefaultSceneFactory sceneFactory, ResourceBundle resourceBundle) {
return new FxmlLoaderFactory(factories, sceneFactory, resourceBundle);
}
@Provides
@@ -50,8 +58,8 @@ abstract class VaultOptionsModule {
@Provides
@FxmlScene(FxmlFile.VAULT_OPTIONS)
@VaultOptionsScoped
static Scene provideVaultOptionsScene(@VaultOptionsWindow FXMLLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene("/fxml/vault_options.fxml");
static Scene provideVaultOptionsScene(@VaultOptionsWindow FxmlLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene(FxmlFile.VAULT_OPTIONS);
}
// ------------------
@@ -5,7 +5,7 @@ import dagger.Module;
import dagger.Provides;
import dagger.multibindings.IntoMap;
import org.cryptomator.ui.common.DefaultSceneFactory;
import org.cryptomator.ui.common.FXMLLoaderFactory;
import org.cryptomator.ui.common.FxmlLoaderFactory;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.common.FxControllerKey;
import org.cryptomator.ui.common.FxmlFile;
@@ -26,8 +26,8 @@ abstract class WrongFileAlertModule {
@Provides
@WrongFileAlertWindow
@WrongFileAlertScoped
static FXMLLoaderFactory provideFxmlLoaderFactory(Map<Class<? extends FxController>, Provider<FxController>> factories, DefaultSceneFactory sceneFactory, ResourceBundle resourceBundle) {
return new FXMLLoaderFactory(factories, sceneFactory, resourceBundle);
static FxmlLoaderFactory provideFxmlLoaderFactory(Map<Class<? extends FxController>, Provider<FxController>> factories, DefaultSceneFactory sceneFactory, ResourceBundle resourceBundle) {
return new FxmlLoaderFactory(factories, sceneFactory, resourceBundle);
}
@Provides
@@ -45,8 +45,8 @@ abstract class WrongFileAlertModule {
@Provides
@FxmlScene(FxmlFile.WRONGFILEALERT)
@WrongFileAlertScoped
static Scene provideWrongFileAlertScene(@WrongFileAlertWindow FXMLLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene("/fxml/wrongfilealert.fxml");
static Scene provideWrongFileAlertScene(@WrongFileAlertWindow FxmlLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene(FxmlFile.WRONGFILEALERT);
}
// ------------------
@@ -12,7 +12,7 @@
<?import javafx.scene.shape.Circle?>
<VBox xmlns:fx="http://javafx.com/fxml"
xmlns="http://javafx.com/javafx"
fx:controller="org.cryptomator.ui.common.ErrorController"
fx:controller="org.cryptomator.ui.error.GenericErrorController"
prefWidth="450"
prefHeight="450"
spacing="12"
@@ -36,7 +36,7 @@
<ButtonBar buttonMinWidth="120" buttonOrder="B+C">
<buttons>
<Button text="%generic.button.back" ButtonBar.buttonData="BACK_PREVIOUS" onAction="#back" visible="${controller.previousScenePresent}"/>
<Button text="%generic.button.back" ButtonBar.buttonData="BACK_PREVIOUS" onAction="#back" visible="${controller.returnScenePresent}"/>
<Button text="%generic.button.cancel" ButtonBar.buttonData="CANCEL_CLOSE" onAction="#close"/>
</buttons>
</ButtonBar>
@@ -3,7 +3,6 @@
<?import org.cryptomator.ui.controls.FontAwesome5IconView?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Hyperlink?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.Region?>
<?import javafx.scene.layout.VBox?>
@@ -25,18 +24,20 @@
<FontAwesome5IconView glyph="KEY" glyphSize="15"/>
</graphic>
</Button>
<Hyperlink text="%main.vaultDetail.optionsBtn" onAction="#showVaultOptions">
<Hyperlink text="%main.vaultDetail.passwordSavedInKeychain" visible="${controller.passwordSaved}" onAction="#showKeyVaultOptions">
<graphic>
<FontAwesome5IconView glyph="COG"/>
<FontAwesome5IconView glyph="LOCK"/>
</graphic>
</Hyperlink>
<Region VBox.vgrow="ALWAYS"/>
<HBox alignment="CENTER_RIGHT" spacing="6">
<Label styleClass="label-small,label-muted" text="%main.vaultDetail.passwordSavedInKeychain" visible="${controller.passwordSaved}">
<HBox alignment="BOTTOM_RIGHT">
<Button text="%main.vaultDetail.optionsBtn" minWidth="120" onAction="#showVaultOptions">
<graphic>
<FontAwesome5IconView styleClass="glyph-icon-muted" glyph="LOCK"/>
<FontAwesome5IconView glyph="COG"/>
</graphic>
</Label>
</Button>
</HBox>
</children>
</VBox>
@@ -2,10 +2,8 @@
<?import org.cryptomator.ui.controls.FontAwesome5IconView?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ContextMenu?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.ListView?>
<?import javafx.scene.control.MenuItem?>
<?import javafx.scene.layout.Region?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.layout.VBox?>
@@ -15,13 +13,9 @@
fx:controller="org.cryptomator.ui.mainwindow.VaultListController"
minWidth="206">
<StackPane VBox.vgrow="ALWAYS">
<ListView fx:id="vaultList" editable="true">
<ListView fx:id="vaultList" editable="true" fixedCellSize="60">
<contextMenu>
<ContextMenu>
<items>
<MenuItem text="%main.vaultlist.contextMenu.remove" onAction="#didClickRemoveVault" disable="${controller.noVaultSelected}"/>
</items>
</ContextMenu>
<fx:include source="vault_list_contextmenu.fxml"/>
</contextMenu>
</ListView>
<VBox visible="${controller.emptyVaultList}" spacing="6" alignment="CENTER">
@@ -13,6 +13,7 @@
prefWidth="200"
spacing="12"
alignment="CENTER_LEFT">
<!-- Remark Check the containing list view for a fixed cell size before editing height properties -->
<padding>
<Insets topRightBottomLeft="12"/>
</padding>
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.ContextMenu?>
<?import javafx.scene.control.MenuItem?>
<ContextMenu xmlns:fx="http://javafx.com/fxml"
xmlns="http://javafx.com/javafx"
fx:controller="org.cryptomator.ui.mainwindow.VaultListContextMenuController">
<items>
<MenuItem fx:id="revealEntry" text="%main.vaultlist.contextMenu.reveal" onAction="#didClickRevealVault" visible="${controller.selectedVaultLockable}"/>
<MenuItem fx:id="lockEntry" text="%main.vaultlist.contextMenu.lock" onAction="#didClickLockVault" visible="${controller.selectedVaultLockable}"/>
<MenuItem fx:id="unlockEntry" text="%main.vaultlist.contextMenu.unlock" onAction="#didClickUnlockVault" visible="${controller.selectedVaultUnlockable &amp;&amp; !controller.selectedVaultPassphraseStored}"/>
<MenuItem fx:id="unlockNowEntry" text="%main.vaultlist.contextMenu.unlockNow" onAction="#didClickUnlockVault" visible="${controller.selectedVaultUnlockable &amp;&amp; controller.selectedVaultPassphraseStored}"/>
<MenuItem fx:id="optionsEntry" text="%main.vaultlist.contextMenu.vaultoptions" onAction="#didClickShowVaultOptions" disable="${!controller.selectedVaultUnlockable}"/>
<MenuItem fx:id="removeEntry" text="%main.vaultlist.contextMenu.remove" onAction="#didClickRemoveVault" disable="${!controller.selectedVaultRemovable}"/>
</items>
</ContextMenu>
@@ -12,7 +12,7 @@
tabClosingPolicy="UNAVAILABLE"
tabDragPolicy="FIXED">
<tabs>
<Tab fx:id="generalTab" text="%vaultOptions.general">
<Tab fx:id="generalTab" id="GENERAL" text="%vaultOptions.general">
<graphic>
<FontAwesome5IconView glyph="WRENCH"/>
</graphic>
@@ -20,7 +20,7 @@
<fx:include source="/fxml/vault_options_general.fxml"/>
</content>
</Tab>
<Tab fx:id="mountTab" text="%vaultOptions.mount">
<Tab fx:id="mountTab" id="MOUNT" text="%vaultOptions.mount">
<graphic>
<FontAwesome5IconView glyph="HDD"/>
</graphic>
@@ -28,7 +28,7 @@
<fx:include source="/fxml/vault_options_mount.fxml"/>
</content>
</Tab>
<Tab fx:id="keyTab" text="%vaultOptions.masterkey">
<Tab fx:id="keyTab" id="KEY" text="%vaultOptions.masterkey">
<graphic>
<FontAwesome5IconView glyph="KEY"/>
</graphic>
@@ -96,12 +96,12 @@ forgetPassword.confirmBtn=Forget Password
# Unlock
unlock.title=Unlock Vault
unlock.passwordPrompt=Enter password for "%s":
unlock.savePassword=Save Password
unlock.savePassword=Remember Password
unlock.unlockBtn=Unlock
## Success
unlock.success.message=Unlocked "%s" successfully! Your vault is now accessible.
unlock.success.message=Unlocked "%s" successfully! Your vault is now accessible via its virtual drive.
unlock.success.rememberChoice=Remember choice, don't show this again
unlock.success.revealBtn=Reveal Vault
unlock.success.revealBtn=Reveal Drive
## Failure
unlock.error.heading=Unable to unlock vault
### Invalid Mount Point
@@ -203,7 +203,7 @@ stats.read.accessCount=Total reads: %d
stats.write.throughput.idle=Write: idle
stats.write.throughput.kibs=Write: %.2f kiB/s
stats.write.throughput.mibs=Write: %.2f MiB/s
stats.write.total.data.none=Data read: -
stats.write.total.data.none=Data written: -
stats.write.total.data.kib=Data written: %.1f kiB
stats.write.total.data.mib=Data written: %.1f MiB
stats.write.total.data.gib=Data written: %.1f GiB
@@ -224,7 +224,12 @@ main.dropZone.dropVault=Add this vault
main.dropZone.unknownDragboardContent=If you want to add a vault, drag it to this window
## Vault List
main.vaultlist.emptyList.onboardingInstruction=Click here to add a vault
main.vaultlist.contextMenu.remove=Remove Vault
main.vaultlist.contextMenu.remove=Remove…
main.vaultlist.contextMenu.lock=Lock
main.vaultlist.contextMenu.unlock=Unlock…
main.vaultlist.contextMenu.unlockNow=Unlock Now
main.vaultlist.contextMenu.vaultoptions=Show Vault Options
main.vaultlist.contextMenu.reveal=Reveal Drive
main.vaultlist.addVaultBtn=Add Vault
## Vault Detail
### Welcome
@@ -95,12 +95,10 @@ forgetPassword.confirmBtn=نسيت كلمة المرور
# Unlock
unlock.title=افتح الحافظة
unlock.passwordPrompt=‮أدخل كلمة السر لـ "%s":
unlock.savePassword=احفظ كلمة المرور
unlock.unlockBtn=افتح
## Success
unlock.success.message=تم فتح المخزن "%s" بنجاح! يمكنك الوصول إليه الآن.
unlock.success.rememberChoice=تذكر اختياري ولا تظهر هذا مرة أخرى
unlock.success.revealBtn=افتح الحافظة
unlock.success.revealBtn=اظهار القرص
## Failure
unlock.error.heading=غير قادر على فتح الخزنة
### Invalid Mount Point
@@ -196,7 +194,10 @@ main.dropZone.dropVault=أضف هذا المخزن
main.dropZone.unknownDragboardContent=إذا كنت ترغب في إضافة مخزن، قم بسحبه إلى هذه النافذة
## Vault List
main.vaultlist.emptyList.onboardingInstruction=انقر هنا لإضافة خزنة
main.vaultlist.contextMenu.remove=حذف الخزنة…
main.vaultlist.contextMenu.lock=قفل
main.vaultlist.contextMenu.unlock=فتح…
main.vaultlist.contextMenu.unlockNow=افتح الان
main.vaultlist.contextMenu.reveal=اظهار القرص
main.vaultlist.addVaultBtn=أضِف مخزنًا
## Vault Detail
### Welcome
@@ -95,71 +95,225 @@ forgetPassword.confirmBtn=Zaboravili ste šifru
# Unlock
unlock.title=Otključaj sef
unlock.passwordPrompt=Unesite lozinku za "%s":
unlock.savePassword=Snimi lozinku
unlock.unlockBtn=Otključaj
## Success
unlock.success.message=Uspješno ste otključali "%s"! Vaš sef je sada dostupan.
unlock.success.rememberChoice=Zapamtite izbor, ne pokazujte ovo ponovo
unlock.success.revealBtn=Otkrij sef
unlock.success.revealBtn=Otkrij pogon
## Failure
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.
unlock.error.invalidMountPoint.existing=Tačka povezivanja "%s" već postoji ili nadređeni folder nedostaje.
# Lock
## Force
lock.forced.heading=Zaključavanje nije uspjelo
lock.forced.message=Zaključavanje "%s" blokirano je operacijama na čekanju ili otvorenim datotekama. Možete prisilno zaključati ovaj sef, međutim prekid U / I-a može rezultirati gubitkom nespremljenih podataka.
lock.forced.confirmBtn=Prisilno zaključaj
## Failure
lock.fail.heading=Zaključavanje sefa nije uspjelo.
lock.fail.message=Sef "%s" nije moguće zaključati. Osigurajte da je nespremljeni rad sačuvan negdje drugdje i da su važne operacije čitanja / pisanja završene. Da biste zatvorili sef, zaustavite Cryptomator proces.
# Migration
migration.title=Nadogradi sef
## Start
migration.start.prompt=Sef "%s" treba ažurirati na noviji format. Prije nastavka, provjerite da nije na čekanju sinkronizacija koja utječe na ovaj sef.
migration.start.confirm=Da, moj sef je u potpunosti sinhroniziran
## Run
migration.run.enterPassword=Unesite lozinku za "%s"
migration.run.startMigrationBtn=Nadogradi sef
migration.run.progressHint=Ovo bi moglo potrajati…
## Sucess
migration.success.nextStepsInstructions="%s" je uspješno nadograđen.\nSada možete otključati svoj sef.
migration.success.unlockNow=Otključaj sada
## Missing file system capabilities
migration.error.missingFileSystemCapabilities.title=Nepodržan tip datoteke
migration.error.missingFileSystemCapabilities.description=Migracija nije započeta, jer se vaš sef nalazi u neadekvatnom sistemu datoteka.
migration.error.missingFileSystemCapabilities.reason.LONG_FILENAMES=Sistem datoteka ne podržava duga imena datoteka.
migration.error.missingFileSystemCapabilities.reason.LONG_PATHS=Sistem datoteka ne podržava duga imena datoteka.
migration.error.missingFileSystemCapabilities.reason.READ_ACCESS=Sistem datoteka ne dozvoljava čitanje.
migration.error.missingFileSystemCapabilities.reason.WRITE_ACCESS=Sistem datoteka ne dozvoljava pisanje.
## Impossible
migration.impossible.heading=Sef se ne može nadograditi
migration.impossible.reason=Sef se ne može automatski migrirati jer njegovo mjesto za pohranu ili pristupna točka nisu kompatibilni.
migration.impossible.moreInfo=Sef se i dalje može otvoriti sa starijom verzijom. Za upute o ručnom migriranju sefa posjetite
# Preferences
preferences.title=Postavke
## General
preferences.general=Generalno
preferences.general.theme=Izgled
preferences.general.theme.automatic=Automatski
preferences.general.theme.light=Svijetlo
preferences.general.theme.dark=Tamno
preferences.general.unlockThemes=Otključaj tamni mod
preferences.general.showMinimizeButton=Pokaži dugme za minimiziranje
preferences.general.showTrayIcon=Prikaži tray ikonu (potrebnan restart)
preferences.general.startHidden=Sakrij prozor prilikom pokretanja Cryptomatora
preferences.general.debugLogging=Omogući evidenciju otklanjanja pogrešaka
preferences.general.debugDirectory=Pokaži dnevnik podataka
preferences.general.autoStart=Pokreni Cryptomator pri pokretanju sistema
preferences.general.keychainBackend=Pohrani lozinku sa
preferences.general.keychainBackend.org.cryptomator.linux.keychain.SecretServiceKeychainAccess=Gnome Keyring
preferences.general.keychainBackend.org.cryptomator.linux.keychain.KDEWalletKeychainAccess=KDE Wallet
preferences.general.keychainBackend.org.cryptomator.macos.keychain.MacSystemKeychainAccess=macOS Keychain Access
preferences.general.keychainBackend.org.cryptomator.windows.keychain.WindowsProtectedKeychainAccess=Windows Data Protection
preferences.general.interfaceOrientation=Orijentacija Interfejsa
preferences.general.interfaceOrientation.ltr=S lijeva ka desno
preferences.general.interfaceOrientation.rtl=Sa desna ka lijevo
## Volume
preferences.volume=Virtuelni pogon
preferences.volume.type=Tip volumena
preferences.volume.webdav.port=WebDAV Port
preferences.volume.webdav.scheme=WebDAV Scheme
## Updates
preferences.updates=Ažuriranja
preferences.updates.currentVersion=Trenutna verzija: %s
preferences.updates.autoUpdateCheck=Automatski provjeri ima li ažuriranja
preferences.updates.checkNowBtn=Provjeri sada
preferences.updates.updateAvailable=Dostupno ažuriranje na verziju %s.
## Donation Key
preferences.donationKey=Donacija
preferences.donationKey.registeredFor=Registrovan za %s
preferences.donationKey.noDonationKey=Nije pronađen važeći ključ za donaciju. To je poput licence, ali za sjajne ljude koji koriste besplatni softver. ;-)
preferences.donationKey.getDonationKey=Nabavite ključ za donaciju
## About
preferences.about=O programu
# Vault Statistics
stats.title=Statistika za %s
stats.cacheHitRate=Brzina učitavanja u predmemoriju
## Read
stats.read.throughput.idle=Čitaj: U pripravnosti
stats.read.throughput.kibs=Čitanje: %.2f kiB/s
stats.read.throughput.mibs=Čitanje: %.2f MiB/s
stats.read.total.data.none=Pročitano podataka: -
stats.read.total.data.kib=Pročitano podataka: %.1f kiB
stats.read.total.data.mib=Pročitano podataka: %.1f MiB
stats.read.total.data.gib=Pročitano podataka: %.1f GiB
stats.decr.total.data.none=Otključani podaci: -
stats.decr.total.data.kib=Otključano podataka: %.1f kiB
stats.decr.total.data.mib=Otključano podataka: %.1f MiB
stats.decr.total.data.gib=Otključano podataka: %.1f GiB
stats.read.accessCount=Ukupno pročitano: %d
## Write
stats.write.throughput.idle=Pisanje: U pripravnosti
stats.write.throughput.kibs=Upisano: %.2f kiB/s
stats.write.throughput.mibs=Upisano: %.2f MiB/s
stats.write.total.data.none=Podaci su upisani:-
stats.write.total.data.kib=Upisano podataka: %.1f kiB
stats.write.total.data.mib=Upisano podataka: %.1f MiB
stats.write.total.data.gib=Upisano podataka: %.1f GiB
stats.encr.total.data.none=Otključano podataka: -
stats.encr.total.data.kib=Otključano podataka: %.1f kiB
stats.encr.total.data.mib=Otključano podataka: %.1f MiB
stats.encr.total.data.gib=Otključano podataka: %.1f GiB
stats.write.accessCount=Ukupno upisano: %d
# Main Window
main.closeBtn.tooltip=Zatvori
main.minimizeBtn.tooltip=Minimiziraj
main.preferencesBtn.tooltip=Postavke
main.debugModeEnabled.tooltip=Omogućen je mod otklanjanja pogrešaka
main.donationKeyMissing.tooltip=Molimo razmislite o doniranju
## Drag 'n' Drop
main.dropZone.dropVault=Dodajte ovaj sef
main.dropZone.unknownDragboardContent=Ako želite dodati sef, povucite ga u ovaj prozor
## Vault List
main.vaultlist.emptyList.onboardingInstruction=Kliknite ovdje da dodate sef
main.vaultlist.contextMenu.lock=Zaključaj
main.vaultlist.contextMenu.unlock=Otključaj…
main.vaultlist.contextMenu.unlockNow=Otključaj sada
main.vaultlist.contextMenu.reveal=Otkrij pogon
main.vaultlist.addVaultBtn=Dodaj sef
## Vault Detail
### Welcome
main.vaultDetail.welcomeOnboarding=Hvala što ste izabrali Cryptomator za zaštitu podataka. Ako vam je potrebna pomoć, pogledajte naše vodiče za početak:
### Locked
main.vaultDetail.lockedStatus=ZAKLJUČANO
main.vaultDetail.unlockBtn=Otključaj…
main.vaultDetail.unlockNowBtn=Otključaj sada
main.vaultDetail.optionsBtn=Opcije sefa
main.vaultDetail.passwordSavedInKeychain=Šifra sačuvana
### Unlocked
main.vaultDetail.unlockedStatus=OTKLJUČANO
main.vaultDetail.accessLocation=Sadržaj Vašeg sefa je dostupan ovdje:
main.vaultDetail.revealBtn=Otkrij pogon
main.vaultDetail.lockBtn=Zaključaj
main.vaultDetail.bytesPerSecondRead=Čitaj:
main.vaultDetail.bytesPerSecondWritten=Piši:
main.vaultDetail.throughput.idle=u stanju mirovanja
main.vaultDetail.throughput.kbps=%.1f kiB/s
main.vaultDetail.throughput.mbps=%.1f MiB/s
main.vaultDetail.stats=Statistika sefa
### Missing
main.vaultDetail.missing.info=Cryptomator nije mogao pronaći disk na ovoj lokaciji.
main.vaultDetail.missing.recheck=Provjeri ponovo
main.vaultDetail.missing.remove=Ukloni sa liste sefova…
main.vaultDetail.missing.changeLocation=Promijeni lokaciju sefa…
### Needs Migration
main.vaultDetail.migrateButton=Nadogradi sef
main.vaultDetail.migratePrompt=Da biste mogli pristupiti svom sefu, morate ga nadograditi na novi format
# Wrong File Alert
wrongFileAlert.title=Kako enkriptovati podatke
wrongFileAlert.header.title=Da li ste pokušali enkriptovati ove datoteke?
wrongFileAlert.header.lead=U tu svrhu Cryptomator kreira volumen u vašem upravljačkom sistemu.
wrongFileAlert.instruction.0=Da biste enkriptovali datoteke, slijedite ove korake:
wrongFileAlert.instruction.1=1. Otključajte sef.
wrongFileAlert.instruction.2=2. Kliknite "Otkrivanje" da biste otvorili volumen u vašem upravitelju datotekama.
wrongFileAlert.instruction.3=3. Dodajte datoteke u ovaj disk.
wrongFileAlert.link=Za dalju podršku, posjetite
# Vault Options
## General
vaultOptions.general=Generalno
vaultOptions.general.vaultName=Ime sefa
vaultOptions.general.unlockAfterStartup=Otključaj sef pri pokretanju Cryptomatora
vaultOptions.general.actionAfterUnlock=Nakon uspješnog otključavanja
vaultOptions.general.actionAfterUnlock.ignore=Ne radi ništa
vaultOptions.general.actionAfterUnlock.reveal=Otkrij pogon
vaultOptions.general.actionAfterUnlock.ask=Pitaj
## Mount
vaultOptions.mount=Povezivanje
vaultOptions.mount.readonly=Samo čitanje
vaultOptions.mount.customMountFlags=Prilagođena obilježja povezivanja
vaultOptions.mount.winDriveLetterOccupied=zauzeto
vaultOptions.mount.mountPoint=Tačka povezivanja
vaultOptions.mount.mountPoint.auto=Automatski odaberi pogodnu lokaciju
vaultOptions.mount.mountPoint.driveLetter=Koristi dodjeljeno slovo (oznaku) diska
vaultOptions.mount.mountPoint.custom=Prilagođena adresa
vaultOptions.mount.mountPoint.directoryPickerButton=Odaberi…
vaultOptions.mount.mountPoint.directoryPickerTitle=Izaberi praznu mapu
## Master Key
vaultOptions.masterkey=Šifra
vaultOptions.masterkey.changePasswordBtn=Promjeni lozinku
vaultOptions.masterkey.forgetSavedPasswordBtn=Zaborav spremljenu šifru
vaultOptions.masterkey.recoveryKeyExpanation=Ključ za oporavak je vaše jedino sredstvo za vraćanje pristupa sefu ako izgubite lozinku.
vaultOptions.masterkey.showRecoveryKeyBtn=Pokaži ključ za oporavak
vaultOptions.masterkey.recoverPasswordBtn=Povrati šifru
# Recovery Key
recoveryKey.title=Ključ za oporavak
recoveryKey.enterPassword.prompt=Unesite šifru da biste prikazali ključ za oporavak za "%s":
recoveryKey.display.message=Sljedeći ključ za oporavak može se koristiti za vraćanje pristupa "%s":
recoveryKey.display.StorageHints=Pohranite ga negdje vrlo sigurno, npr.:\n • Spremite ga pomoću menadžera lozinki\n • Spremite ga na USB disk\n • Odštampajte ga na papiru
recoveryKey.recover.prompt=Unesite ključ za oporavak za "%s":
recoveryKey.recover.validKey=Ključ za oporavak je ispravan
recoveryKey.printout.heading=Cryptomator Ključ za oporavak za \n"%s"\n
# New Password
newPassword.promptText=Unesi novu šifru
newPassword.reenterPassword=Potvrdi novu šifru
newPassword.passwordsMatch=Šifra odgovara!
newPassword.passwordsDoNotMatch=Šifre se ne poklapaju
passwordStrength.messageLabel.tooShort=Upotrijebite najmanje %d znakova
passwordStrength.messageLabel.0=Veoma slabo
passwordStrength.messageLabel.1=Slabo
passwordStrength.messageLabel.2=Dovoljno
passwordStrength.messageLabel.3=Sigurno
passwordStrength.messageLabel.4=Veoma sigurno
# Quit
quit.prompt=Zatvoriti prijavu? Postoje otključani sefovi.
quit.lockAndQuit=Zaključaj i zatvori
@@ -98,9 +98,8 @@ unlock.passwordPrompt=Introduïu la contrasenya de "%s":
unlock.savePassword=Recorda la contrasenya
unlock.unlockBtn=Desbloqueja
## Success
unlock.success.message="%s" s'ha desbloquejat correctament! Ja es pot accedir a la caixa forta.
unlock.success.rememberChoice=Recorda l'elecció. No ho tornis a mostrar.
unlock.success.revealBtn=Mostra la caixa forta
unlock.success.revealBtn=Mostra la unitat
## Failure
unlock.error.heading=No ha estat possible desblocar la caixa forta
### Invalid Mount Point
@@ -202,7 +201,7 @@ stats.read.accessCount=Lectures en total: %d
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.none=Dades escrites
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
@@ -223,7 +222,10 @@ 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.contextMenu.lock=Bloqueja
main.vaultlist.contextMenu.unlock=Desbloca…
main.vaultlist.contextMenu.unlockNow=Desbloqueja ara
main.vaultlist.contextMenu.reveal=Mostra la unitat
main.vaultlist.addVaultBtn=Afegir una caixa forta
## Vault Detail
### Welcome
@@ -95,12 +95,11 @@ forgetPassword.confirmBtn=Zapomenout heslo
# Unlock
unlock.title=Odemknout trezor
unlock.passwordPrompt=Zadejte heslo pro "%s":
unlock.savePassword=Uložit heslo
unlock.savePassword=Zapamatovat heslo
unlock.unlockBtn=Odemknout
## Success
unlock.success.message=Trezor "%s" byl úspěšně odemčen a nyní je dostupný.
unlock.success.rememberChoice=Pamatovat si volbu, nezobrazovat to znovu
unlock.success.revealBtn=Zobrazit trezor
unlock.success.revealBtn=Zobrazit jednotku
## Failure
unlock.error.heading=Nelze odemknout trezor
### Invalid Mount Point
@@ -109,6 +108,8 @@ unlock.error.invalidMountPoint.existing=Připojovací bod %s již existuje nebo
# Lock
## Force
lock.forced.heading=Běžné uzamčení selhalo
lock.forced.confirmBtn=Přesto uzamknout
## Failure
# Migration
@@ -197,7 +198,7 @@ stats.read.accessCount=Celkem přečteno: %d
stats.write.throughput.idle=Zápis: nečinný
stats.write.throughput.kibs=Zápis: %.2f kiB/s
stats.write.throughput.mibs=Zápis: %.2f MiB/s
stats.write.total.data.none=Přečteno: -
stats.write.total.data.none=Zapsaná data: -
stats.write.total.data.kib=Zapsáno: %.1f kiB
stats.write.total.data.mib=Zapsáno: %.1f MiB
stats.write.total.data.gib=Zapsáno: %.1f GiB
@@ -218,7 +219,11 @@ main.dropZone.dropVault=Přidat tento trezor
main.dropZone.unknownDragboardContent=Pokud chcete přidat trezor, přetáhněte jej do tohoto okna
## Vault List
main.vaultlist.emptyList.onboardingInstruction=Klikněte zde pro přidání nového trezoru
main.vaultlist.contextMenu.remove=Odstranit trezor
main.vaultlist.contextMenu.remove=Odstranit…
main.vaultlist.contextMenu.lock=Zamknout
main.vaultlist.contextMenu.unlock=Odemknout…
main.vaultlist.contextMenu.unlockNow=Odemknout nyní
main.vaultlist.contextMenu.reveal=Zobrazit jednotku
main.vaultlist.addVaultBtn=Přidat trezor
## Vault Detail
### Welcome
@@ -95,12 +95,12 @@ forgetPassword.confirmBtn=Passwort vergessen
# Unlock
unlock.title=Tresor entsperren
unlock.passwordPrompt=Gib das Passwort für „%s“ ein:
unlock.savePassword=Passwort speichern
unlock.savePassword=Passwort merken
unlock.unlockBtn=Entsperren
## Success
unlock.success.message=„%s“ erfolgreich entsperrt! Nun kannst du auf deinen Tresor zugreifen.
unlock.success.message=„%s“ erfolgreich entsperrt! Nun kannst du über das virtuelle Laufwerk auf deinen Tresor zugreifen.
unlock.success.rememberChoice=Auswahl speichern und nicht mehr anzeigen
unlock.success.revealBtn=Tresor anzeigen
unlock.success.revealBtn=Laufwerk anzeigen
## Failure
unlock.error.heading=Tresor konnte nicht entsperrt werden
### Invalid Mount Point
@@ -189,28 +189,28 @@ stats.cacheHitRate=Cache-Trefferrate
stats.read.throughput.idle=Lesen: Leerlauf
stats.read.throughput.kibs=Lesen: %.2f kiB/s
stats.read.throughput.mibs=Lesen: %.2f MiB/s
stats.read.total.data.none=Daten gelesen: -
stats.read.total.data.kib=Daten gelesen: %.1f kiB
stats.read.total.data.mib=Daten gelesen: %.1f MiB
stats.read.total.data.gib=Daten gelesen: %.1f GiB
stats.decr.total.data.none=Daten entschlüsselt: -
stats.decr.total.data.kib=Daten entschlüsselt: %.1f kiB
stats.decr.total.data.mib=Daten entschlüsselt: %.1f MiB
stats.decr.total.data.gib=Daten entschlüsselt: %.1f GiB
stats.read.accessCount=Gesamt gelesen: %d
stats.read.total.data.none=Gelesen: -
stats.read.total.data.kib=Gelesen: %.1f kiB
stats.read.total.data.mib=Gelesen: %.1f MiB
stats.read.total.data.gib=Gelesen: %.1f GiB
stats.decr.total.data.none=Entschlüsselt: -
stats.decr.total.data.kib=Entschlüsselt: %.1f kiB
stats.decr.total.data.mib=Entschlüsselt: %.1f MiB
stats.decr.total.data.gib=Entschlüsselt: %.1f GiB
stats.read.accessCount=Lesezugriffe: %d
## Write
stats.write.throughput.idle=Schreiben: Leerlauf
stats.write.throughput.kibs=Schreiben: %.2f kiB/s
stats.write.throughput.mibs=Schreiben: %.2f MiB/s
stats.write.total.data.none=Daten gelesen: -
stats.write.total.data.kib=Daten geschrieben: %.1f kiB
stats.write.total.data.mib=Daten geschrieben: %.1f MiB
stats.write.total.data.gib=Daten geschrieben: %.1f GiB
stats.encr.total.data.none=Daten verschlüsselt: -
stats.encr.total.data.kib=Daten verschlüsselt: %.1f kiB
stats.encr.total.data.mib=Datenverschlüsselt: %.1f MiB
stats.encr.total.data.gib=Daten verschlüsselt: %.1f GiB
stats.write.accessCount=Gesamt geschrieben: %d
stats.write.total.data.none=Geschrieben: -
stats.write.total.data.kib=Geschrieben: %.1f kiB
stats.write.total.data.mib=Geschrieben: %.1f MiB
stats.write.total.data.gib=Geschrieben: %.1f GiB
stats.encr.total.data.none=Verschlüsselt: -
stats.encr.total.data.kib=Verschlüsselt: %.1f kiB
stats.encr.total.data.mib=Verschlüsselt: %.1f MiB
stats.encr.total.data.gib=Verschlüsselt: %.1f GiB
stats.write.accessCount=Schreibzugriffe: %d
# Main Window
main.closeBtn.tooltip=Schließen
@@ -223,7 +223,12 @@ main.dropZone.dropVault=Diesen Tresor hinzufügen
main.dropZone.unknownDragboardContent=Wenn Sie einen Tresor hinzufügen möchten, ziehen Sie ihn in dieses Fenster
## Vault List
main.vaultlist.emptyList.onboardingInstruction=Klicke hier, um einen Tresor hinzuzufügen
main.vaultlist.contextMenu.remove=Tresor entfernen…
main.vaultlist.contextMenu.remove=Entfernen
main.vaultlist.contextMenu.lock=Sperren
main.vaultlist.contextMenu.unlock=Entsperren …
main.vaultlist.contextMenu.unlockNow=Jetzt entsperren
main.vaultlist.contextMenu.vaultoptions=Tresoroptionen anzeigen
main.vaultlist.contextMenu.reveal=Laufwerk anzeigen
main.vaultlist.addVaultBtn=Tresor hinzufügen
## Vault Detail
### Welcome
@@ -280,7 +285,7 @@ vaultOptions.mount.customMountFlags=Benutzerdefinierte Mount-Flags
vaultOptions.mount.winDriveLetterOccupied=belegt
vaultOptions.mount.mountPoint=Einhängepunkt
vaultOptions.mount.mountPoint.auto=Automatisch einen passenden Ort auswählen
vaultOptions.mount.mountPoint.driveLetter=Zugewiesenen Laufwerksbuchstaben verwenden
vaultOptions.mount.mountPoint.driveLetter=Laufwerksbuchstaben zuweisen
vaultOptions.mount.mountPoint.custom=Pfad selbst wählen
vaultOptions.mount.mountPoint.directoryPickerButton=Durchsuchen …
vaultOptions.mount.mountPoint.directoryPickerTitle=Wähle ein leeres Verzeichnis
@@ -95,12 +95,11 @@ forgetPassword.confirmBtn=Ξέχασα τον κωδικό πρόσβασης
# Unlock
unlock.title=Ξεκλείδωμα Vault
unlock.passwordPrompt=Εισάγετε τον κωδικό για "%s":
unlock.savePassword=Αποθήκευση κωδικού
unlock.savePassword=Απομνημόνευση κωδικού πρόσβασης
unlock.unlockBtn=Ξεκλείδωμα
## Success
unlock.success.message="%s" ξεκλειδώθηκε επιτυχώς! Το vault σας είναι διαθέσιμο.
unlock.success.rememberChoice=Απομνημόνευση επιλογής, μην ρωτήσεις ξανά
unlock.success.revealBtn=Αποκάλυψη Vault
unlock.success.revealBtn=Αποκάλυψη εικονικού δίσκου
## Failure
unlock.error.heading=Αδυναμία ξεκλειδώματος vault
### Invalid Mount Point
@@ -149,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=Αποκάλυψη αρχείων καταγραφής
@@ -200,7 +201,7 @@ stats.read.accessCount=Συνολικές αναγνώσεις: %d
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.none=Δεδομένα που γράφηκαν: -
stats.write.total.data.kib=Δεδομένα που γράφτηκαν: %.1f kiB
stats.write.total.data.mib=Δεδομένα που γράφτηκαν: %.1f MiB
stats.write.total.data.gib=Δεδομένα που γράφτηκαν: %.1f GiB
@@ -221,7 +222,10 @@ main.dropZone.dropVault=Προσθήκη vault
main.dropZone.unknownDragboardContent=Αν θέλετε να προσθέσετε ένα vault, σύρετε το σε αυτό το παράθυρο
## Vault List
main.vaultlist.emptyList.onboardingInstruction=Κάντε κλικ εδώ για να προσθέσετε ένα vault
main.vaultlist.contextMenu.remove=Διαγραφή Vault…
main.vaultlist.contextMenu.lock=Κλείδωμα
main.vaultlist.contextMenu.unlock=Ξεκλείδωμα…
main.vaultlist.contextMenu.unlockNow=Ξεκλείδωμα τώρα
main.vaultlist.contextMenu.reveal=Αποκάλυψη εικονικού δίσκου
main.vaultlist.addVaultBtn=Προσθήκη Vault
## Vault Detail
### Welcome
@@ -95,12 +95,12 @@ forgetPassword.confirmBtn=Olvidar contraseña
# Unlock
unlock.title=Desbloquear bóveda
unlock.passwordPrompt=Ingresar contraseña para "%s":
unlock.savePassword=Guardar contraseña
unlock.savePassword=Recordar contraseña
unlock.unlockBtn=Desbloquear
## Success
unlock.success.message=¡"%s" se desbloqueó con éxito! La bóveda ya es accesible.
unlock.success.message=¡Desbloqueo de "%s" exitoso! Su bóveda ahora es accesible a través de su unidad virtual.
unlock.success.rememberChoice=Recordar opción y no mostrar de nuevo
unlock.success.revealBtn=Revelar bóveda
unlock.success.revealBtn=Revelar unidad
## Failure
unlock.error.heading=No se puede desbloquear la bóveda
### Invalid Mount Point
@@ -202,7 +202,7 @@ stats.read.accessCount=Total leídos: %d
stats.write.throughput.idle=Escritura: inactivo
stats.write.throughput.kibs=Escritura: %.2f kiB/s
stats.write.throughput.mibs=Escritura: %.2f MiB/s
stats.write.total.data.none=Datos leídos: -
stats.write.total.data.none=Datos escritos:-
stats.write.total.data.kib=Datos escritos: %.1f kiB
stats.write.total.data.mib=Datos escritos: %.1f MiB
stats.write.total.data.gib=Datos escritos: %.1f GiB
@@ -223,7 +223,12 @@ main.dropZone.dropVault=Añadir esta bóveda
main.dropZone.unknownDragboardContent=Si desea añadir una bóveda, arrástrela a esta ventana
## Vault List
main.vaultlist.emptyList.onboardingInstruction=Hacer clic aquí para añadir una bóveda
main.vaultlist.contextMenu.remove=Eliminar bóveda
main.vaultlist.contextMenu.remove=Eliminar…
main.vaultlist.contextMenu.lock=Bloquear
main.vaultlist.contextMenu.unlock=Desbloquear…
main.vaultlist.contextMenu.unlockNow=Desbloquear ahora
main.vaultlist.contextMenu.vaultoptions=Mostrar opciones de la bóveda
main.vaultlist.contextMenu.reveal=Revelar unidad
main.vaultlist.addVaultBtn=Añadir bóveda
## Vault Detail
### Welcome
@@ -95,12 +95,12 @@ forgetPassword.confirmBtn=Oublier le mot de passe
# Unlock
unlock.title=Déverrouiller le coffre
unlock.passwordPrompt=Entrez le mot de passe pour “%s” :
unlock.savePassword=Enregistrer le mot de passe
unlock.savePassword=Mémoriser le mot de passe
unlock.unlockBtn=Déverrouiller
## Success
unlock.success.message=“%s” déverrouillé ! Le contenu de votre coffre est maintenant accessible.
unlock.success.message=“%s” déverrouillé ! Le contenu de votre coffre est maintenant accessible par son lecteur virtuel.
unlock.success.rememberChoice=Se souvenir de mon choix et ne plus me demander
unlock.success.revealBtn=Révéler le coffre
unlock.success.revealBtn=Révéler le lecteur
## Failure
unlock.error.heading=Impossible de déverrouiller le coffre
### Invalid Mount Point
@@ -202,7 +202,7 @@ stats.read.accessCount=Total des lectures: %d
stats.write.throughput.idle=Écriture : inactif
stats.write.throughput.kibs=Écriture : %.2f kiO/s
stats.write.throughput.mibs=Écriture : %.2f Mo/s
stats.write.total.data.none=Lecture des données : -
stats.write.total.data.none=Données écrites : -
stats.write.total.data.kib=Données écrites : %.1f kiO
stats.write.total.data.mib=Données écrites : %.1f MiO
stats.write.total.data.gib=Données écrites : %.1f GiO
@@ -223,7 +223,12 @@ main.dropZone.dropVault=Ajouter ce coffre
main.dropZone.unknownDragboardContent=Si vous voulez ajouter un coffre, faites-le glisser dans cette fenêtre
## Vault List
main.vaultlist.emptyList.onboardingInstruction=Cliquez ici pour ajouter un coffre
main.vaultlist.contextMenu.remove=Supprimer le coffre
main.vaultlist.contextMenu.remove=Retirer
main.vaultlist.contextMenu.lock=Verrouiller
main.vaultlist.contextMenu.unlock=Déverrouiller…
main.vaultlist.contextMenu.unlockNow=Déverrouiller maintenant
main.vaultlist.contextMenu.vaultoptions=Afficher les options du coffre
main.vaultlist.contextMenu.reveal=Révéler le lecteur
main.vaultlist.addVaultBtn=Ajouter un coffre
## Vault Detail
### Welcome
@@ -106,6 +106,7 @@ main.closeBtn.tooltip=बंद करें
main.preferencesBtn.tooltip=प्राथमिकताएं
## Drag 'n' Drop
## Vault List
main.vaultlist.contextMenu.lock=लॉक करें
main.vaultlist.addVaultBtn=वाउल्ट डालें
## Vault Detail
### Welcome
@@ -1,5 +1,4 @@
# Locale Specific CSS files such as CJK, RTL,...
additionalStyleSheets=
# Generics
## Button
@@ -41,7 +40,6 @@ addvaultwizard.new.namePrompt=A széf neve
### Location
addvaultwizard.new.locationInstruction=Hova mentse a Cryptomator a széf titkosított fájljait?
addvaultwizard.new.locationLabel=Tárolási hely
addvaultwizard.new.locationPrompt=
addvaultwizard.new.directoryPickerLabel=Egyedi hely
addvaultwizard.new.directoryPickerButton=Választás…
addvaultwizard.new.directoryPickerTitle=Könyvtár kiválasztása
@@ -49,7 +47,7 @@ addvaultwizard.new.fileAlreadyExists=Nem lehet a széfet létrehozni ezen a hely
addvaultwizard.new.locationDoesNotExist=Nem lehet a széfet létrehozni ezen a helyen, mert az útvonal legalább egy darabja nem létezik.
addvaultwizard.new.invalidName=Érvénytelen széf elnevezés. Kérjük vegye figyelembe a szabályos könyvtárelnevezésre vonatkozó szabályokat.
### Password
addvaultwizard.new.createVaultBtn=Széf létrehozása
addvaultwizard.new.createVaultBtn=Új széf létrehozása
addvaultwizard.new.generateRecoveryKeyChoice=Nem fog tudni hozzáférni az adataihoz a jelszó nélkül. Akar egy visszaállítási kulcsot arra az esetre, ha elveszíti a jelszavát?
addvaultwizard.new.generateRecoveryKeyChoice.yes=Igen kérem, jobb félni, mint megijedni.
addvaultwizard.new.generateRecoveryKeyChoice.no=Nem köszönöm, nem fogom elveszíteni a jelszavam.
@@ -96,10 +94,8 @@ forgetPassword.confirmBtn=Jelszó elfelejtése
# Unlock
unlock.title=Széf feloldása
unlock.passwordPrompt=Írja be a jelszavát a következő széfhez "%s":
unlock.savePassword=Jelszó mentése
unlock.unlockBtn=Feloldás
## Success
unlock.success.message="%s" sikreresen feloldásra került! Mostmár hozzáférhet a széféhez.
unlock.success.rememberChoice=Jegyezze meg a választást és ne mutassa többet
unlock.success.revealBtn=Széf megjelenítése
## Failure
@@ -108,6 +104,10 @@ unlock.error.heading=Nem lehet feloldani a széfet
unlock.error.invalidMountPoint.notExisting=A csatolási pont "%s" nem egy könyvtár, nem üres vagy nem létezik.
unlock.error.invalidMountPoint.existing=A csatolási pont "%s" már létezik vagy a already exists or szülőmappa hiányzik.
# Lock
## Force
## Failure
# Migration
migration.title=Széf frissítése
## Start
@@ -115,7 +115,7 @@ migration.start.prompt=A "%s" széf formátuma frissítésre szorul. A folytatá
migration.start.confirm=Igen, a széfem teljes mértékben szinkronizálva van
## Run
migration.run.enterPassword=Írja be a jelszót a következőhöz Enter the password for "%s"
migration.run.startMigrationBtn=Széf migrációja
migration.run.startMigrationBtn=Széf frissítése
migration.run.progressHint=Ez eltarthat egy darabig…
## Sucess
migration.success.nextStepsInstructions=A "%s" sikeresen migrálva. \nMost már feloldhatja a széfet.
@@ -146,18 +146,12 @@ preferences.general.debugLogging=Hibakeresési naplózás engedélyezése
preferences.general.debugDirectory=Naplófájlok megjelenítése
preferences.general.autoStart=Cryptomator indítása a rendszerrel együtt
preferences.general.keychainBackend=Itt tárolja a jelszavakat
preferences.general.keychainBackend.org.cryptomator.linux.keychain.SecretServiceKeychainAccess=Gnome Keyring
preferences.general.keychainBackend.org.cryptomator.linux.keychain.KDEWalletKeychainAccess=KDE Wallet
preferences.general.keychainBackend.org.cryptomator.macos.keychain.MacSystemKeychainAccess=macOS Keychain Access
preferences.general.keychainBackend.org.cryptomator.windows.keychain.WindowsProtectedKeychainAccess=Windows Data Protection
preferences.general.interfaceOrientation=Felhasználói felület orientációja
preferences.general.interfaceOrientation.ltr=Balról jobbra
preferences.general.interfaceOrientation.rtl=Jobbról balra
## Volume
preferences.volume=Virtuális meghajtó
preferences.volume.type=Kötet tipusa
preferences.volume.webdav.port=WebDAV Port
preferences.volume.webdav.scheme=WebDAV Scheme
## Updates
preferences.updates=Frissítések
preferences.updates.currentVersion=Jelenlegi verzió: %s
@@ -192,7 +186,6 @@ stats.read.accessCount=Összes olvasás: %d
stats.write.throughput.idle=Írás: tétlen
stats.write.throughput.kibs=Írás: %.2f kiB/s
stats.write.throughput.mibs=Írás: %.2f MiB/s
stats.write.total.data.none=Írott adat: -
stats.write.total.data.kib=Írott adat: %.1f kiB
stats.write.total.data.mib=Írott adat: %.1f MiB
stats.write.total.data.gib=Írott adat: %.1f GiB
@@ -213,7 +206,10 @@ main.dropZone.dropVault=Adja hozzá ezt a széfet
main.dropZone.unknownDragboardContent=Ha egy széfet szeretne hozzáadni, akkor húzza át erre az ablakra.
## Vault List
main.vaultlist.emptyList.onboardingInstruction=Kattintson ide egy széf hozzáadásához
main.vaultlist.contextMenu.remove=Széf eltávolítása…
main.vaultlist.contextMenu.lock=Zárolás
main.vaultlist.contextMenu.unlock=Feloldás…
main.vaultlist.contextMenu.unlockNow=Azonnali feloldás
main.vaultlist.contextMenu.reveal=Széf megjelenítése
main.vaultlist.addVaultBtn=Széf hozzáadása
## Vault Detail
### Welcome
@@ -232,8 +228,6 @@ main.vaultDetail.lockBtn=Zárolás
main.vaultDetail.bytesPerSecondRead=Olvasás:
main.vaultDetail.bytesPerSecondWritten=Írás:
main.vaultDetail.throughput.idle=tétlen
main.vaultDetail.throughput.kbps=%.1f kiB/s
main.vaultDetail.throughput.mbps=%.1f MiB/s
main.vaultDetail.stats=Széf statisztika
### Missing
main.vaultDetail.missing.info=A Cryptomator nem talált széfet ezen az útvonalon.
@@ -262,22 +256,22 @@ vaultOptions.general.unlockAfterStartup=A széf feloldása a Cryptomator indít
vaultOptions.general.actionAfterUnlock=Sikeres feloldás után
vaultOptions.general.actionAfterUnlock.ignore=Ne tegyen semmit
vaultOptions.general.actionAfterUnlock.reveal=Jelenítse meg a kötetet
vaultOptions.general.actionAfterUnlock.ask=Kérdezzen
vaultOptions.general.actionAfterUnlock.ask=Kérdez
## Mount
vaultOptions.mount=Csatolás
vaultOptions.mount.readonly=Csak olvasható
vaultOptions.mount=Felcsatolás
vaultOptions.mount.readonly=Csak-olvasható
vaultOptions.mount.customMountFlags=Egyedi csatolási paraméterek
vaultOptions.mount.winDriveLetterOccupied=foglalt
vaultOptions.mount.mountPoint=Csatolási pont
vaultOptions.mount.mountPoint.auto=Válasszon egy megfelelő helyet autómatikusan
vaultOptions.mount.mountPoint.auto=Válasszon egy megfelelő helyet automatikusan
vaultOptions.mount.mountPoint.driveLetter=Használja a kiválasztott meghajtó betűjelét
vaultOptions.mount.mountPoint.custom=Egyedi útvonal
vaultOptions.mount.mountPoint.directoryPickerButton=Kiválasztás
vaultOptions.mount.mountPoint.directoryPickerButton=Kiválaszt…
vaultOptions.mount.mountPoint.directoryPickerTitle=Válasszon egy üres könyvtárat
## Master Key
vaultOptions.masterkey=Jelszó
vaultOptions.masterkey.changePasswordBtn=Jelszó megváltoztatása
vaultOptions.masterkey.forgetSavedPasswordBtn=Elmentett jelszó elfelejtése
vaultOptions.masterkey.forgetSavedPasswordBtn=Mentett jelszó törlése
vaultOptions.masterkey.recoveryKeyExpanation=A helyreállítási kulcs az egyetlen módja annak, hogy visszaállítsa a széfhez való hozzáférést, ha elveíti a jelszavát.
vaultOptions.masterkey.showRecoveryKeyBtn=Visszaállítási kulcs megjelenítése
vaultOptions.masterkey.recoverPasswordBtn=Jelszó visszaállítása
@@ -292,8 +286,8 @@ recoveryKey.recover.validKey=Ez egy érvényes visszaállítási kulcs
recoveryKey.printout.heading=Cryptomator visszaállítási kulcs\n"%s"\n
# New Password
newPassword.promptText=Írja be az új jelszavát
newPassword.reenterPassword=Erősítse meg az új jelszavát
newPassword.promptText=Adjon meg egy új jelszót
newPassword.reenterPassword=Az új jelszó megerősítése
newPassword.passwordsMatch=A jelszavak megegyeznek!
newPassword.passwordsDoNotMatch=A jelszavak nem egyeznek meg
passwordStrength.messageLabel.tooShort=Használjon legalább %d karaktert
@@ -109,6 +109,7 @@ main.closeBtn.tooltip=Tutup
main.preferencesBtn.tooltip=Preferensi
## Drag 'n' Drop
## Vault List
main.vaultlist.contextMenu.lock=Gembok
main.vaultlist.addVaultBtn=Tambah Brankas
## Vault Detail
### Welcome
@@ -95,12 +95,11 @@ forgetPassword.confirmBtn=Password dimenticata
# Unlock
unlock.title=Sblocca Cassaforte
unlock.passwordPrompt=Inserisci la password per "%s":
unlock.savePassword=Salva password
unlock.savePassword=Ricorda la Password
unlock.unlockBtn=Sblocca
## Success
unlock.success.message=Sbloccato "%s" con successo! La tua cassaforte è ora accessibile.
unlock.success.rememberChoice=Ricorda la scelta, non mostrare ancora
unlock.success.revealBtn=Rivela Cassaforte
unlock.success.revealBtn=Visualizza disco
## Failure
unlock.error.heading=Impossibile sbloccare la cassaforte
### Invalid Mount Point
@@ -200,7 +199,7 @@ stats.read.accessCount=Totale lettura: %d
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.none=Dati scritti: -
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
@@ -221,7 +220,10 @@ main.dropZone.dropVault=Aggiungi questa cassaforte
main.dropZone.unknownDragboardContent=Se vuoi aggiungere una cassaforte, trascinala in questa finestra
## Vault List
main.vaultlist.emptyList.onboardingInstruction=Clicca qui per aggiungere una cassaforte
main.vaultlist.contextMenu.remove=Rimuovi Cassaforte…
main.vaultlist.contextMenu.lock=Blocca
main.vaultlist.contextMenu.unlock=Sblocca…
main.vaultlist.contextMenu.unlockNow=Sblocca adesso
main.vaultlist.contextMenu.reveal=Visualizza disco
main.vaultlist.addVaultBtn=Aggiungi Cassaforte
## Vault Detail
### Welcome
@@ -95,12 +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.revealBtn=金庫を表示
unlock.success.revealBtn=ドライブを表示
## Failure
unlock.error.heading=金庫の解錠に失敗
### Invalid Mount Point
@@ -202,7 +201,7 @@ stats.read.accessCount=合計読み取り: %d
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.none=書き込み済みデータ: -
stats.write.total.data.kib=書き込み済みデータ: %.1f kiB
stats.write.total.data.mib=書き込み済みデータ: %.1f MiB
stats.write.total.data.gib=書き込み済みデータ: %.1f GiB
@@ -223,7 +222,10 @@ main.dropZone.dropVault=この金庫を追加
main.dropZone.unknownDragboardContent=このウィンドウにドラッグして、金庫を追加
## Vault List
main.vaultlist.emptyList.onboardingInstruction=ここをクリックして金庫を追加
main.vaultlist.contextMenu.remove=金庫を削除...
main.vaultlist.contextMenu.lock=施錠
main.vaultlist.contextMenu.unlock=解錠...
main.vaultlist.contextMenu.unlockNow=今すぐ解錠
main.vaultlist.contextMenu.reveal=ドライブを表示
main.vaultlist.addVaultBtn=金庫を追加
## Vault Detail
### Welcome
@@ -67,7 +67,7 @@ addvault.new.readme.storageLocation.10=만일 도움이 필요하신 경우, 다
addvault.new.readme.accessLocation.fileName=WELCOME.rtf
addvault.new.readme.accessLocation.1=🔐️ 암호화 된 볼륨 🔐️
addvault.new.readme.accessLocation.2=이것은 당신의 Vault 접근 위치입니다.
addvault.new.readme.accessLocation.3=이 볼륨에 추가된 모든 파일은 Cryptomator로 암호화됩니다. 다른 드라이브/폴더처럼 작업할 수 있습니다. 볼륨의 내용은 복호화 된 것 처럼 보여질 뿐이며, 모든 파일은 항상 암호화되어 하드디스크에 저장됩니다.
addvault.new.readme.accessLocation.3=이 볼륨에 추가된 모든 파일은 Cryptomator로 암호화됩니다. 다른 드라이브/폴더처럼 작업할 수 있습니다. 볼륨의 내용은 복호화 된 것 처럼 보여지지만, 모든 파일은 항상 암호화되어 하드디스크에 저장됩니다.
addvault.new.readme.accessLocation.4=이 파일은 지우셔도 무방합니다.
## Existing
addvaultwizard.existing.instruction=기존 Vault 의 "masterkey.cryptomator" 파일을 선택하여 주십시요.
@@ -95,12 +95,11 @@ forgetPassword.confirmBtn=비밀번호 분실
# Unlock
unlock.title=Vault 잠금해제
unlock.passwordPrompt="%s"의 비밀번호를 입력하십시요.
unlock.savePassword=비밀번호 저장
unlock.savePassword=비밀번호 기억
unlock.unlockBtn=잠금해제
## Success
unlock.success.message="%s"의 잠금해제가 성공적으로 수행되었습니다! 이제 이 Vault의 접근이 가능합니다.
unlock.success.rememberChoice=선택 기억함, 다시 묻지 않음
unlock.success.revealBtn=Vault 표시
unlock.success.revealBtn=드라이브 표시
## Failure
unlock.error.heading=Vault 잠금을 해제 할 수 없습니다.
### Invalid Mount Point
@@ -149,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=Log 파일 표시
@@ -200,7 +201,7 @@ stats.read.accessCount=총 읽기 횟수: %d
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.none=데이터 기록됨: -
stats.write.total.data.kib=데이터 쓰기: %.1f kiB
stats.write.total.data.mib=데이터 쓰기: %.1f MiB
stats.write.total.data.gib=데이터 쓰기: %.1f GiB
@@ -221,7 +222,10 @@ main.dropZone.dropVault=이 Vault를 추가
main.dropZone.unknownDragboardContent=Vault를 추가하려면, 이 창에 드래그 하십시요.
## Vault List
main.vaultlist.emptyList.onboardingInstruction=Vault를 추가하기 위해 이곳을 클릭합니다.
main.vaultlist.contextMenu.remove=Vault 제거...
main.vaultlist.contextMenu.lock=잠금
main.vaultlist.contextMenu.unlock=잠금해제...
main.vaultlist.contextMenu.unlockNow=지금 잠금해제
main.vaultlist.contextMenu.reveal=드라이브 표시
main.vaultlist.addVaultBtn=Vault 추가
## Vault Detail
### Welcome
@@ -292,7 +296,7 @@ vaultOptions.masterkey.recoverPasswordBtn=비밀번호 복구
# Recovery Key
recoveryKey.title=복구 키
recoveryKey.enterPassword.prompt="%s"의 복구 키를 표시하려면 비밀번호를 입력하여 주십시요.
recoveryKey.enterPassword.prompt="%s"의 복구 키를 표시하려면 비밀번호를 입력해 주세요.
recoveryKey.display.message="%s" 데이터 접근을 복원하는데 사용 할 수 있는 복구 키 입니다:
recoveryKey.display.StorageHints=매우 안전한곳에 보관하십시요. 예시:\n • 비밀번호 관리자를 사용하여 저장\n • USB 플래시 드라이브에 저장\n • 종이에 출력
recoveryKey.recover.prompt="%s"의 복구키를 입력하십시요:
@@ -300,7 +304,7 @@ recoveryKey.recover.validKey=올바른 복구 키 입니다.
recoveryKey.printout.heading=Cryptomator 복구 키\n"%s"\n
# New Password
newPassword.promptText=새 비밀번호를 입력하십시요.
newPassword.promptText=새 비밀번호를 입력하세요
newPassword.reenterPassword=새 비밀번호를 확인하여 주십시요.
newPassword.passwordsMatch=비밀번호가 일치합니다!
newPassword.passwordsDoNotMatch=비밀번호가 일치하지 않습니다.
@@ -93,11 +93,9 @@ forgetPassword.confirmBtn=Aizmirst paroli
# Unlock
unlock.title=Atslēgt glabātuvi
unlock.passwordPrompt=Ievadiet "%s" paroli:
unlock.savePassword=Saglabāt paroli
unlock.unlockBtn=Atslēgt
## Success
unlock.success.message="%s" sekmīgi atslēgts! Jūsu glabātuve tagad ir pieejama.
unlock.success.revealBtn=Atklāt glabātuvi
unlock.success.revealBtn=Atklāt disku
## Failure
### Invalid Mount Point
@@ -172,6 +170,9 @@ main.dropZone.dropVault=Pievienot šo glabātuvi
main.dropZone.unknownDragboardContent=Ja jūs vēlaties pievienot glabātuvi, velciet to uz šo logu
## Vault List
main.vaultlist.emptyList.onboardingInstruction=Spied šeit, lai pievienotu glabātuvi
main.vaultlist.contextMenu.lock=Aizslēgt
main.vaultlist.contextMenu.unlockNow=Atslēgt tagad
main.vaultlist.contextMenu.reveal=Atklāt disku
main.vaultlist.addVaultBtn=Pievienot glabātuvi
## Vault Detail
### Welcome
@@ -95,12 +95,11 @@ forgetPassword.confirmBtn=Glem passord
# Unlock
unlock.title=Lås opp hvelvet
unlock.passwordPrompt=Skriv inn passordet for "%s":
unlock.savePassword=Lagre passord
unlock.savePassword=Husk passord
unlock.unlockBtn=Lås opp
## Success
unlock.success.message=Vellykket opplåsning av "%s"! Hvelvet ditt er nå tilgjengelig.
unlock.success.rememberChoice=Husk valget - ikke vis dette igjen
unlock.success.revealBtn=Gjør hvelvet synlig
unlock.success.revealBtn=Gjør enheten synlig
## Failure
unlock.error.heading=Klarer ikke å låse opp hvelvet
### Invalid Mount Point
@@ -202,7 +201,7 @@ stats.read.accessCount=Lesninger totalt: %d
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.none=Data skrevet: -
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
@@ -223,7 +222,10 @@ main.dropZone.dropVault=Legg til dette hvelvet
main.dropZone.unknownDragboardContent=Hvis du vil legge til et hvelv, kan du dra det til dette vinduet
## Vault List
main.vaultlist.emptyList.onboardingInstruction=Klikk her for å legge til et hvelv
main.vaultlist.contextMenu.remove=Fjern hvelvet…
main.vaultlist.contextMenu.lock=Lås
main.vaultlist.contextMenu.unlock=Lås opp…
main.vaultlist.contextMenu.unlockNow=Lås opp nå
main.vaultlist.contextMenu.reveal=Gjør enheten synlig
main.vaultlist.addVaultBtn=Legg til hvelv
## Vault Detail
### Welcome
@@ -95,12 +95,10 @@ forgetPassword.confirmBtn=Wachtwoord vergeten
# Unlock
unlock.title=Kluis ontgrendelen
unlock.passwordPrompt=Voer wachtwoord voor "%s" in:
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
unlock.success.revealBtn=Toon Schijf
## Failure
unlock.error.heading=Kan kluis niet ontgrendelen
### Invalid Mount Point
@@ -202,7 +200,6 @@ stats.read.accessCount=Totaal gelezen: %d
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
@@ -223,7 +220,10 @@ 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.contextMenu.lock=Vergrendel
main.vaultlist.contextMenu.unlock=Ontgrendelen…
main.vaultlist.contextMenu.unlockNow=Nu Ontgrendelen
main.vaultlist.contextMenu.reveal=Toon Schijf
main.vaultlist.addVaultBtn=Kluis toevoegen
## Vault Detail
### Welcome
@@ -94,12 +94,10 @@ forgetPassword.confirmBtn=Gløym passord
# Unlock
unlock.title=Lås opp kvelven
unlock.passwordPrompt=Skriv inn passordet for "%s":
unlock.savePassword=Lagre passordet
unlock.unlockBtn=Låse opp
## Success
unlock.success.message=Vellykka opplåsning av "%s"! Kvelven din er no tilgjengeleg.
unlock.success.rememberChoice=Hugs valet - ikkje vis dette igjen
unlock.success.revealBtn=Gjer kvelven synleg
unlock.success.revealBtn=Gjer eininga synleg
## Failure
### Invalid Mount Point
@@ -179,6 +177,10 @@ main.dropZone.dropVault=Legg til denne kvelven
main.dropZone.unknownDragboardContent=Viss du vil legga til ein kvelv, kan du dra det til dette vindauget
## Vault List
main.vaultlist.emptyList.onboardingInstruction=Klikk her for å legga til ein kvelv
main.vaultlist.contextMenu.lock=Lås
main.vaultlist.contextMenu.unlock=Lås opp…
main.vaultlist.contextMenu.unlockNow=Lås opp no
main.vaultlist.contextMenu.reveal=Gjer eininga synleg
main.vaultlist.addVaultBtn=Legg til kvelv
## Vault Detail
### Welcome
@@ -95,12 +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.revealBtn=ਾਲਟ ਦਿਖਾਓ
unlock.success.revealBtn=ਡਰਾਇਵ ਦਿਖਾਓ
## Failure
unlock.error.heading=ਵਾਲਟ ਅਣ-ਲਾਕ ਕਰਨ ਲਈ ਅਸਮਰੱਥ
### Invalid Mount Point
@@ -149,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=ਲਾਗ ਫਾਇਲਾਂ ਦਿਖਾਓ
@@ -200,7 +201,7 @@ stats.read.accessCount=ਕੁੱਲ ਪੜ੍ਹੇ: %d
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.none=ਲਿਖਿਆ ਡਾਟਾ: -
stats.write.total.data.kib=ਡਾਟਾ ਲਿਖਿਆ: %.1f kiB
stats.write.total.data.mib=ਡਾਟਾ ਲਿਖਿਆ: %.1f MiB
stats.write.total.data.gib=ਡਾਟਾ ਲਿਖਿਆ: %.1f GiB
@@ -221,7 +222,10 @@ main.dropZone.dropVault=ਇਹ ਵਾਲਟ ਜੋੜੋ
main.dropZone.unknownDragboardContent=ਜੇ ਤੁਸੀਂ ਵਾਲਟ ਜੋੜਨਾ ਚਾਹੁੰਦੇ ਹੋ ਤਾਂ ਇਸ ਨੂੰ ਬੰਦ ਵਿੰਡੋ ਉੱਤੇ ਖਿੱਚੋ
## Vault List
main.vaultlist.emptyList.onboardingInstruction=ਵਾਲਟ ਜੋੜਨ ਲਈ ਇੱਥੇ ਕਲਿੱਕ ਕਰੋ
main.vaultlist.contextMenu.remove=…ਵਾਲਟ ਹਟਾਓ
main.vaultlist.contextMenu.lock=ਲਾਕ ਕਰੋ
main.vaultlist.contextMenu.unlock=ਅਣ-ਲਾਕ ਕਰੋ…
main.vaultlist.contextMenu.unlockNow=ਹੁਣੇ ਅਣ-ਲਾਕ ਕਰੋ
main.vaultlist.contextMenu.reveal=ਡਰਾਇਵ ਦਿਖਾਓ
main.vaultlist.addVaultBtn=ਵਾਲਟ ਜੋੜੋ
## Vault Detail
### Welcome
@@ -98,9 +98,9 @@ unlock.passwordPrompt=Wprowadź hasło dla "%s":
unlock.savePassword=Zapamiętaj hasło
unlock.unlockBtn=Odblokuj
## Success
unlock.success.message="%s" został odblokowany! Twój sejf jest teraz dostępny.
unlock.success.message=Odblokowano "%s" pomyślnie! Twój sejf jest teraz dostępny za pomocą dysku wirtualnego.
unlock.success.rememberChoice=Zapamiętaj wybór, nie pokazuj tego ponownie
unlock.success.revealBtn=Otwórz sejf
unlock.success.revealBtn=Ujawnij Dysk
## Failure
unlock.error.heading=Nie można odblokować sejfu
### Invalid Mount Point
@@ -202,7 +202,7 @@ stats.read.accessCount=Całkowite odczyty: %d
stats.write.throughput.idle=Zapis: bezczynny
stats.write.throughput.kibs=Zapis: %.2f kiB/s
stats.write.throughput.mibs=Zapis: %.2f kiB/s
stats.write.total.data.none=Dane odczytywane: -
stats.write.total.data.none=Zapisane dane: -
stats.write.total.data.kib=Zapisane dane: %.1f kiB
stats.write.total.data.mib=Zapisane dane: %.1f MiB
stats.write.total.data.gib=Zapisane dane: %.1f kiB
@@ -223,7 +223,12 @@ main.dropZone.dropVault=Dodaj ten sejf
main.dropZone.unknownDragboardContent=Jeśli chcesz dodać sejf, przeciągnij go do tego okna
## Vault List
main.vaultlist.emptyList.onboardingInstruction=Kliknij tutaj, aby dodać sejf
main.vaultlist.contextMenu.remove=Usuń sejf
main.vaultlist.contextMenu.remove=Usuń…
main.vaultlist.contextMenu.lock=Zablokuj
main.vaultlist.contextMenu.unlock=Odblokuj…
main.vaultlist.contextMenu.unlockNow=Odblokuj teraz
main.vaultlist.contextMenu.vaultoptions=Pokaż opcje sejfu
main.vaultlist.contextMenu.reveal=Otwórz lokalizację
main.vaultlist.addVaultBtn=Dodaj sejf
## Vault Detail
### Welcome
@@ -86,12 +86,9 @@ forgetPassword.confirmBtn=Esqueci a Senha
# Unlock
unlock.title=Destrancar Cofre
unlock.passwordPrompt=Insira a senha para "%s":
unlock.savePassword=Lembrar Senha
unlock.unlockBtn=Destrancar
## Success
unlock.success.message=Desbloqueado "%s" com sucesso! O seu cofre está agora acessível.
unlock.success.rememberChoice=Lembrar escolha, não mostrar isto novamente
unlock.success.revealBtn=Revelar Cofre
## Failure
### Invalid Mount Point
@@ -141,6 +138,8 @@ main.minimizeBtn.tooltip=Minimizar
main.preferencesBtn.tooltip=Preferências
## Drag 'n' Drop
## Vault List
main.vaultlist.contextMenu.lock=Trancar
main.vaultlist.contextMenu.unlockNow=Destrancar agora
main.vaultlist.addVaultBtn=Adicionar Cofre
## Vault Detail
### Welcome
@@ -95,12 +95,11 @@ forgetPassword.confirmBtn=Esquecer Senha
# Unlock
unlock.title=Desbloquear Cofre
unlock.passwordPrompt=Digite a senha para "%s":
unlock.savePassword=Salvar Senha
unlock.savePassword=Lembrar Senha
unlock.unlockBtn=Desbloquear
## Success
unlock.success.message="%s" foi desbloqueado com sucesso! Seu cofre agora está acessível.
unlock.success.rememberChoice=Lembrar opção escolhida, não mostrar isto novamente
unlock.success.revealBtn=Revelar Cofre
unlock.success.revealBtn=Revelar Volume
## Failure
unlock.error.heading=Não foi possível desbloquear o cofre
### Invalid Mount Point
@@ -202,7 +201,7 @@ stats.read.accessCount=Total de leituras: %d
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.none=Dados gravados: -
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
@@ -223,7 +222,10 @@ main.dropZone.dropVault=Adicionar este cofre
main.dropZone.unknownDragboardContent=Se você quer adicionar um cofre, arraste-o para esta janela
## Vault List
main.vaultlist.emptyList.onboardingInstruction=Clique aqui para adicionar um cofre
main.vaultlist.contextMenu.remove=Remover Cofre…
main.vaultlist.contextMenu.lock=Bloquear
main.vaultlist.contextMenu.unlock=Desbloquear…
main.vaultlist.contextMenu.unlockNow=Desbloquear Agora
main.vaultlist.contextMenu.reveal=Revelar Volume
main.vaultlist.addVaultBtn=Adicionar Cofre
## Vault Detail
### Welcome
@@ -95,12 +95,12 @@ forgetPassword.confirmBtn=Не помню пароль
# Unlock
unlock.title=Разблокировать хранилище
unlock.passwordPrompt=Введите пароль для "%s"
unlock.savePassword=Сохранить пароль
unlock.savePassword=Запомнить пароль
unlock.unlockBtn=Разблокировать
## Success
unlock.success.message=Разблокировка "%s" успешно выполнена! Доступ в хранилище открыт.
unlock.success.message=Разблокировка "%s" успешно выполнена! Доступ в хранилище открыт через его виртуальный диск.
unlock.success.rememberChoice=Запомнить выбор и больше не спрашивать
unlock.success.revealBtn=Показать хранилище
unlock.success.revealBtn=Показать диск
## Failure
unlock.error.heading=Не удалось разблокировать хранилище
### Invalid Mount Point
@@ -202,7 +202,7 @@ stats.read.accessCount=Всего операций чтения: %d
stats.write.throughput.idle=Запись: бездействие
stats.write.throughput.kibs=Запись: %.2f КиБ/с
stats.write.throughput.mibs=Запись: %.2f МиБ/с
stats.write.total.data.none=Прочитано: -
stats.write.total.data.none=Записано данных: -
stats.write.total.data.kib=Записано: %.1f КиБ
stats.write.total.data.mib=Записано: %.1f МиБ
stats.write.total.data.gib=Записано: %.1f ГиБ
@@ -223,7 +223,12 @@ main.dropZone.dropVault=Добавить это хранилище
main.dropZone.unknownDragboardContent=Если вы хотите добавить хранилище, перетащите его в это окно
## Vault List
main.vaultlist.emptyList.onboardingInstruction=Нажмите здесь, чтобы добавить хранилище
main.vaultlist.contextMenu.remove=Удалить хранилище
main.vaultlist.contextMenu.remove=Удалить…
main.vaultlist.contextMenu.lock=Заблокировать
main.vaultlist.contextMenu.unlock=Разблокировка…
main.vaultlist.contextMenu.unlockNow=Разблокировать
main.vaultlist.contextMenu.vaultoptions=Параметры хранилища
main.vaultlist.contextMenu.reveal=Показать диск
main.vaultlist.addVaultBtn=Добавить хранилище
## Vault Detail
### Welcome
@@ -93,11 +93,9 @@ forgetPassword.confirmBtn=Zabudnuté heslo
# Unlock
unlock.title=Odomknúť trezor
unlock.passwordPrompt=Zadajte heslo pre "%s":
unlock.savePassword=Uložiť heslo
unlock.savePassword=Odomknúť.uložiťHeslo
unlock.unlockBtn=Odomknúť
## Success
unlock.success.message=Úspešne sa odomkol "%s"! Váš trezor je teraz prístupný.
unlock.success.revealBtn=Odhaliť trezor
## Failure
unlock.error.heading=Nie je možné odomknúť účet
### Invalid Mount Point
@@ -125,6 +123,8 @@ migration.success.unlockNow=Odomknúť teraz
preferences.title=Predvoľby
## General
preferences.general.theme.automatic=Automaticky
preferences.general.showMinimizeButton=Predvoľba.hlavná.ukážMinimalizujTlačítko
preferences.general.showTrayIcon=Predvoľba.hlavná.ukážIkonaSytémovejlišty
preferences.general.keychainBackend.org.cryptomator.linux.keychain.SecretServiceKeychainAccess=Gnome klúčenka
preferences.general.keychainBackend.org.cryptomator.linux.keychain.KDEWalletKeychainAccess=KDE účet
preferences.general.keychainBackend.org.cryptomator.macos.keychain.MacSystemKeychainAccess=maccOS reťazový prístup
@@ -154,7 +154,7 @@ stats.read.accessCount=Spolu načítané: %d
stats.write.throughput.idle=Zápis: nečinnosť
stats.write.throughput.kibs=Zápis: %.2f KiB/s
stats.write.throughput.mibs=Zápis: %.2f MiB/s
stats.write.total.data.none=Čítanie dát: -
stats.write.total.data.none=štatistika.zápis.celkové.dáta.nič
stats.write.total.data.kib=Zapísaných dát: %.1f kiB
stats.write.total.data.mib=Zapísaných dát: %.1f MiB
stats.write.total.data.gib=Zapísaných dát: %.1f GiB
@@ -170,7 +170,9 @@ main.preferencesBtn.tooltip=Predvoľby
main.debugModeEnabled.tooltip=Debagovací mód je aktivovaný
## Drag 'n' Drop
## Vault List
main.vaultlist.contextMenu.remove=Odstrániť peňaženku…
main.vaultlist.contextMenu.lock=Uzamknúť
main.vaultlist.contextMenu.unlock=Odomknúť…
main.vaultlist.contextMenu.unlockNow=Odomknúť teraz
main.vaultlist.addVaultBtn=Pridať trezor
## Vault Detail
### Welcome

Some files were not shown because too many files have changed in this diff Show More