mirror of
https://github.com/cryptomator/cryptomator.git
synced 2026-09-22 07:54:19 +00:00
Compare commits
5
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d013497c48 | ||
|
|
8691eec42b | ||
|
|
0f9d572677 | ||
|
|
baee23b6d4 | ||
|
|
7bfd0ed341 |
@@ -10,7 +10,7 @@ on:
|
|||||||
required: false
|
required: false
|
||||||
|
|
||||||
env:
|
env:
|
||||||
JAVA_VERSION: 20
|
JAVA_VERSION: 19
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
get-version:
|
get-version:
|
||||||
@@ -54,7 +54,7 @@ jobs:
|
|||||||
--verbose
|
--verbose
|
||||||
--output runtime
|
--output runtime
|
||||||
--module-path "${JAVA_HOME}/jmods"
|
--module-path "${JAVA_HOME}/jmods"
|
||||||
--add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,javafx.base,javafx.graphics,javafx.controls,javafx.fxml,jdk.unsupported,jdk.crypto.ec,jdk.security.auth,jdk.accessibility,jdk.management.jfr
|
--add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,javafx.base,javafx.graphics,javafx.controls,javafx.fxml,jdk.unsupported,jdk.crypto.ec,jdk.security.auth,jdk.accessibility,jdk.management.jfr,jdk.zipfs
|
||||||
--strip-native-commands
|
--strip-native-commands
|
||||||
--no-header-files
|
--no-header-files
|
||||||
--no-man-pages
|
--no-man-pages
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ on:
|
|||||||
types: [labeled]
|
types: [labeled]
|
||||||
|
|
||||||
env:
|
env:
|
||||||
JAVA_VERSION: 20
|
JAVA_VERSION: 19
|
||||||
|
|
||||||
defaults:
|
defaults:
|
||||||
run:
|
run:
|
||||||
@@ -53,9 +53,8 @@ jobs:
|
|||||||
body: |-
|
body: |-
|
||||||
:construction: Work in Progress
|
:construction: Work in Progress
|
||||||
|
|
||||||
⏳ Please be patient, the builds are still [running](https://github.com/cryptomator/cryptomator/actions). New versions of Cryptomator can be found here in a few moments. ⏳
|
Please be patient, the builds are still running. We will publish new versions of Cryptomator here in a few moments.
|
||||||
|
|
||||||
As usual, the GPG signatures can be checked using [our public key `5811 7AFA 1F85 B3EE C154 677D 615D 449F E6E6 A235`](https://gist.github.com/cryptobot/211111cf092037490275f39d408f461a).
|
As usual, the GPG signatures can be checked using [our public key `5811 7AFA 1F85 B3EE C154 677D 615D 449F E6E6 A235`](https://gist.github.com/cryptobot/211111cf092037490275f39d408f461a).
|
||||||
|
|
||||||
---
|
---
|
||||||
<!-- Don't forget to include the 💾 SHA-256 checksums of release artifacts: -->
|
<!-- Don't forget to include the 💾 SHA-256 checksums of release artifacts: -->
|
||||||
@@ -19,9 +19,9 @@ on:
|
|||||||
type: boolean
|
type: boolean
|
||||||
|
|
||||||
env:
|
env:
|
||||||
JAVA_VERSION: 20
|
JAVA_VERSION: 19
|
||||||
OPENJFX_JMODS_AMD64: 'https://download2.gluonhq.com/openjfx/20.0.1/openjfx-20.0.1_linux-x64_bin-jmods.zip'
|
OPENJFX_JMODS_AMD64: 'https://download2.gluonhq.com/openjfx/19.0.2.1/openjfx-19.0.2.1_linux-x64_bin-jmods.zip'
|
||||||
OPENJFX_JMODS_AARCH64: 'https://download2.gluonhq.com/openjfx/20.0.1/openjfx-20.0.1_linux-aarch64_bin-jmods.zip'
|
OPENJFX_JMODS_AARCH64: 'https://download2.gluonhq.com/openjfx/19.0.2.1/openjfx-19.0.2.1_linux-aarch64_bin-jmods.zip'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
@@ -45,7 +45,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
sudo add-apt-repository ppa:coffeelibs/openjdk
|
sudo add-apt-repository ppa:coffeelibs/openjdk
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get install debhelper devscripts dput coffeelibs-jdk-${{ env.JAVA_VERSION }} libgtk2.0-0
|
sudo apt-get install debhelper devscripts dput coffeelibs-jdk-19 libgtk2.0-0
|
||||||
- name: Setup Java
|
- name: Setup Java
|
||||||
uses: actions/setup-java@v3
|
uses: actions/setup-java@v3
|
||||||
with:
|
with:
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ on:
|
|||||||
value: ${{ jobs.determine-version.outputs.type }}
|
value: ${{ jobs.determine-version.outputs.type }}
|
||||||
|
|
||||||
env:
|
env:
|
||||||
JAVA_VERSION: 20
|
JAVA_VERSION: 19
|
||||||
JAVA_DIST: 'temurin'
|
JAVA_DIST: 'temurin'
|
||||||
JAVA_CACHE: 'maven'
|
JAVA_CACHE: 'maven'
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ on:
|
|||||||
required: false
|
required: false
|
||||||
|
|
||||||
env:
|
env:
|
||||||
JAVA_VERSION: 20
|
JAVA_VERSION: 19
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
get-version:
|
get-version:
|
||||||
@@ -70,7 +70,7 @@ jobs:
|
|||||||
--verbose
|
--verbose
|
||||||
--output runtime
|
--output runtime
|
||||||
--module-path "${JAVA_HOME}/jmods"
|
--module-path "${JAVA_HOME}/jmods"
|
||||||
--add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,javafx.base,javafx.graphics,javafx.controls,javafx.fxml,jdk.unsupported,jdk.crypto.ec,jdk.accessibility,jdk.management.jfr
|
--add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,javafx.base,javafx.graphics,javafx.controls,javafx.fxml,jdk.unsupported,jdk.crypto.ec,jdk.accessibility,jdk.management.jfr,jdk.zipfs
|
||||||
--strip-native-commands
|
--strip-native-commands
|
||||||
--no-header-files
|
--no-header-files
|
||||||
--no-man-pages
|
--no-man-pages
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ on:
|
|||||||
pull_request:
|
pull_request:
|
||||||
|
|
||||||
env:
|
env:
|
||||||
JAVA_VERSION: 20
|
JAVA_VERSION: 19
|
||||||
|
|
||||||
defaults:
|
defaults:
|
||||||
run:
|
run:
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ on:
|
|||||||
- 'hotfix/**'
|
- 'hotfix/**'
|
||||||
|
|
||||||
env:
|
env:
|
||||||
JAVA_VERSION: 20
|
JAVA_VERSION: 19
|
||||||
|
|
||||||
defaults:
|
defaults:
|
||||||
run:
|
run:
|
||||||
|
|||||||
@@ -14,11 +14,11 @@ on:
|
|||||||
|
|
||||||
|
|
||||||
env:
|
env:
|
||||||
JAVA_VERSION: 20
|
JAVA_VERSION: 19
|
||||||
JAVA_DIST: 'temurin'
|
JAVA_DIST: 'temurin'
|
||||||
JAVA_CACHE: 'maven'
|
JAVA_CACHE: 'maven'
|
||||||
JFX_JMODS_URL: 'https://download2.gluonhq.com/openjfx/20.0.1/openjfx-20.0.1_windows-x64_bin-jmods.zip'
|
JFX_JMODS_URL: 'https://download2.gluonhq.com/openjfx/19.0.2.1/openjfx-19.0.2.1_windows-x64_bin-jmods.zip'
|
||||||
JFX_JMODS_HASH: 'D00767334C43B8832B5CF10267D34CA8F563D187C4655B73EB6020DD79C054B5'
|
JFX_JMODS_HASH: 'B7CF2CAD2468842B3B78D99F6C0555771499A36FA1F1EE3DD1B9A4597F1FAB86'
|
||||||
|
|
||||||
defaults:
|
defaults:
|
||||||
run:
|
run:
|
||||||
@@ -51,7 +51,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
curl --output jfxjmods.zip -L "${{ env.JFX_JMODS_URL }}"
|
curl --output jfxjmods.zip -L "${{ env.JFX_JMODS_URL }}"
|
||||||
if(!(Get-FileHash -Path jfxjmods.zip -Algorithm SHA256).Hash.equals("${{ env.JFX_JMODS_HASH }}")) {
|
if(!(Get-FileHash -Path jfxjmods.zip -Algorithm SHA256).Hash.equals("${{ env.JFX_JMODS_HASH }}")) {
|
||||||
throw "Wrong checksum of JMOD archive downloaded from ${{ env.JFX_JMODS_URL }}.";
|
exit 1;
|
||||||
}
|
}
|
||||||
Expand-Archive -Path jfxjmods.zip -DestinationPath jfxjmods
|
Expand-Archive -Path jfxjmods.zip -DestinationPath jfxjmods
|
||||||
Get-ChildItem -Path jfxjmods -Recurse -Filter "*.jmod" | ForEach-Object { Move-Item -Path $_ -Destination $_.Directory.Parent}
|
Get-ChildItem -Path jfxjmods -Recurse -Filter "*.jmod" | ForEach-Object { Move-Item -Path $_ -Destination $_.Directory.Parent}
|
||||||
@@ -83,7 +83,7 @@ jobs:
|
|||||||
--verbose
|
--verbose
|
||||||
--output runtime
|
--output runtime
|
||||||
--module-path "jfxjmods;${JAVA_HOME}/jmods"
|
--module-path "jfxjmods;${JAVA_HOME}/jmods"
|
||||||
--add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,javafx.base,javafx.graphics,javafx.controls,javafx.fxml,jdk.unsupported,jdk.crypto.ec,jdk.accessibility,jdk.management.jfr
|
--add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,javafx.base,javafx.graphics,javafx.controls,javafx.fxml,jdk.unsupported,jdk.crypto.ec,jdk.accessibility,jdk.management.jfr,jdk.zipfs
|
||||||
--strip-native-commands
|
--strip-native-commands
|
||||||
--no-header-files
|
--no-header-files
|
||||||
--no-man-pages
|
--no-man-pages
|
||||||
|
|||||||
Generated
+1
-1
@@ -8,7 +8,7 @@
|
|||||||
</list>
|
</list>
|
||||||
</option>
|
</option>
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_20_PREVIEW" project-jdk-name="20" project-jdk-type="JavaSDK">
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_19" default="true" project-jdk-name="19" project-jdk-type="JavaSDK">
|
||||||
<output url="file://$PROJECT_DIR$/out" />
|
<output url="file://$PROJECT_DIR$/out" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
Vendored
+1
-1
@@ -24,7 +24,7 @@ ${JAVA_HOME}/bin/jlink \
|
|||||||
--verbose \
|
--verbose \
|
||||||
--output runtime \
|
--output runtime \
|
||||||
--module-path "${JAVA_HOME}/jmods" \
|
--module-path "${JAVA_HOME}/jmods" \
|
||||||
--add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,javafx.base,javafx.graphics,javafx.controls,javafx.fxml,jdk.unsupported,jdk.crypto.ec,jdk.security.auth,jdk.accessibility,jdk.management.jfr \
|
--add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,javafx.base,javafx.graphics,javafx.controls,javafx.fxml,jdk.unsupported,jdk.crypto.ec,jdk.security.auth,jdk.accessibility,jdk.management.jfr,jdk.zipfs \
|
||||||
--strip-native-commands \
|
--strip-native-commands \
|
||||||
--no-header-files \
|
--no-header-files \
|
||||||
--no-man-pages \
|
--no-man-pages \
|
||||||
|
|||||||
@@ -66,8 +66,6 @@
|
|||||||
</content_rating>
|
</content_rating>
|
||||||
|
|
||||||
<releases>
|
<releases>
|
||||||
<release date="2023-06-07" version="1.9.1"/>
|
|
||||||
<release date="2023-05-30" version="1.9.0"/>
|
|
||||||
<release date="2023-04-25" version="1.8.0"/>
|
<release date="2023-04-25" version="1.8.0"/>
|
||||||
<release date="2023-04-07" version="1.7.5"/>
|
<release date="2023-04-07" version="1.7.5"/>
|
||||||
<release date="2023-04-05" version="1.7.4"/>
|
<release date="2023-04-05" version="1.7.4"/>
|
||||||
|
|||||||
Vendored
+1
-1
@@ -2,7 +2,7 @@ Source: cryptomator
|
|||||||
Maintainer: Cryptobot <releases@cryptomator.org>
|
Maintainer: Cryptobot <releases@cryptomator.org>
|
||||||
Section: utils
|
Section: utils
|
||||||
Priority: optional
|
Priority: optional
|
||||||
Build-Depends: debhelper (>=10), coffeelibs-jdk-20, libgtk2.0-0, libgtk-3-0, libxxf86vm1, libgl1
|
Build-Depends: debhelper (>=10), coffeelibs-jdk-19, libgtk2.0-0, libgtk-3-0, libxxf86vm1, libgl1
|
||||||
Standards-Version: 4.5.0
|
Standards-Version: 4.5.0
|
||||||
Homepage: https://cryptomator.org
|
Homepage: https://cryptomator.org
|
||||||
Vcs-Git: https://github.com/cryptomator/cryptomator.git
|
Vcs-Git: https://github.com/cryptomator/cryptomator.git
|
||||||
|
|||||||
Vendored
+2
-2
@@ -4,7 +4,7 @@
|
|||||||
# Uncomment this to turn on verbose mode.
|
# Uncomment this to turn on verbose mode.
|
||||||
#export DH_VERBOSE=1
|
#export DH_VERBOSE=1
|
||||||
|
|
||||||
JAVA_HOME = /usr/lib/jvm/java-20-coffeelibs
|
JAVA_HOME = /usr/lib/jvm/java-19-coffeelibs
|
||||||
DEB_BUILD_ARCH ?= $(shell dpkg-architecture -qDEB_BUILD_ARCH)
|
DEB_BUILD_ARCH ?= $(shell dpkg-architecture -qDEB_BUILD_ARCH)
|
||||||
ifeq ($(DEB_BUILD_ARCH),amd64)
|
ifeq ($(DEB_BUILD_ARCH),amd64)
|
||||||
JMODS_PATH = jmods/amd64:${JAVA_HOME}/jmods
|
JMODS_PATH = jmods/amd64:${JAVA_HOME}/jmods
|
||||||
@@ -27,7 +27,7 @@ override_dh_auto_build:
|
|||||||
$(JAVA_HOME)/bin/jlink \
|
$(JAVA_HOME)/bin/jlink \
|
||||||
--output runtime \
|
--output runtime \
|
||||||
--module-path "${JMODS_PATH}" \
|
--module-path "${JMODS_PATH}" \
|
||||||
--add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,javafx.base,javafx.graphics,javafx.controls,javafx.fxml,jdk.unsupported,jdk.crypto.ec,jdk.security.auth,jdk.accessibility,jdk.management.jfr \
|
--add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,javafx.base,javafx.graphics,javafx.controls,javafx.fxml,jdk.unsupported,jdk.crypto.ec,jdk.security.auth,jdk.accessibility,jdk.management.jfr,jdk.zipfs \
|
||||||
--strip-native-commands \
|
--strip-native-commands \
|
||||||
--no-header-files \
|
--no-header-files \
|
||||||
--no-man-pages \
|
--no-man-pages \
|
||||||
|
|||||||
Vendored
+1
-1
@@ -46,7 +46,7 @@ cp ../../../target/${MAIN_JAR_GLOB} ../../../target/mods
|
|||||||
${JAVA_HOME}/bin/jlink \
|
${JAVA_HOME}/bin/jlink \
|
||||||
--output runtime \
|
--output runtime \
|
||||||
--module-path "${JAVA_HOME}/jmods" \
|
--module-path "${JAVA_HOME}/jmods" \
|
||||||
--add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,jdk.unsupported,jdk.crypto.ec,jdk.accessibility,jdk.management.jfr \
|
--add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,jdk.unsupported,jdk.crypto.ec,jdk.accessibility,jdk.management.jfr,jdk.zipfs \
|
||||||
--strip-native-commands \
|
--strip-native-commands \
|
||||||
--no-header-files \
|
--no-header-files \
|
||||||
--no-man-pages \
|
--no-man-pages \
|
||||||
|
|||||||
Vendored
+1
-1
@@ -51,7 +51,7 @@ if ($clean -and (Test-Path -Path $runtimeImagePath)) {
|
|||||||
--verbose `
|
--verbose `
|
||||||
--output runtime `
|
--output runtime `
|
||||||
--module-path "$Env:JAVA_HOME/jmods" `
|
--module-path "$Env:JAVA_HOME/jmods" `
|
||||||
--add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,jdk.unsupported,jdk.crypto.ec,jdk.accessibility,jdk.management.jfr `
|
--add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,jdk.unsupported,jdk.crypto.ec,jdk.accessibility,jdk.management.jfr,jdk.zipfs `
|
||||||
--strip-native-commands `
|
--strip-native-commands `
|
||||||
--no-header-files `
|
--no-header-files `
|
||||||
--no-man-pages `
|
--no-man-pages `
|
||||||
|
|||||||
Vendored
+2
-10
@@ -70,9 +70,6 @@
|
|||||||
<CustomAction Id="JpDisallowDowngrade" Error="!(loc.DowngradeErrorMessage)" />
|
<CustomAction Id="JpDisallowDowngrade" Error="!(loc.DowngradeErrorMessage)" />
|
||||||
<?endif?>
|
<?endif?>
|
||||||
|
|
||||||
<Binary Id="JpCaDll" SourceFile="wixhelper.dll"/>
|
|
||||||
<CustomAction Id="JpFindRelatedProducts" BinaryKey="JpCaDll" DllEntry="FindRelatedProductsEx" />
|
|
||||||
|
|
||||||
<?ifndef SkipCryptomatorLegacyCheck ?>
|
<?ifndef SkipCryptomatorLegacyCheck ?>
|
||||||
<!-- Block installation if innosetup entry of Cryptomator is found -->
|
<!-- Block installation if innosetup entry of Cryptomator is found -->
|
||||||
<Property Id="OLDEXEINSTALLER">
|
<Property Id="OLDEXEINSTALLER">
|
||||||
@@ -175,12 +172,11 @@
|
|||||||
<?endif?>
|
<?endif?>
|
||||||
|
|
||||||
<?ifndef JpAllowUpgrades ?>
|
<?ifndef JpAllowUpgrades ?>
|
||||||
<Custom Action="JpDisallowUpgrade" After="JpFindRelatedProducts">JP_UPGRADABLE_FOUND</Custom>
|
<Custom Action="JpDisallowUpgrade" After="FindRelatedProducts">JP_UPGRADABLE_FOUND</Custom>
|
||||||
<?endif?>
|
<?endif?>
|
||||||
<?ifndef JpAllowDowngrades ?>
|
<?ifndef JpAllowDowngrades ?>
|
||||||
<Custom Action="JpDisallowDowngrade" After="JpFindRelatedProducts">JP_DOWNGRADABLE_FOUND</Custom>
|
<Custom Action="JpDisallowDowngrade" After="FindRelatedProducts">JP_DOWNGRADABLE_FOUND</Custom>
|
||||||
<?endif?>
|
<?endif?>
|
||||||
<Custom Action="JpFindRelatedProducts" After="FindRelatedProducts"/>
|
|
||||||
|
|
||||||
<!-- Check and fail if Cryptomator is running -->
|
<!-- Check and fail if Cryptomator is running -->
|
||||||
<Custom Action="WixCloseApplications" Before="InstallValidate"></Custom>
|
<Custom Action="WixCloseApplications" Before="InstallValidate"></Custom>
|
||||||
@@ -192,10 +188,6 @@
|
|||||||
<Custom Action="V170MigrateSettings" After="InstallFiles">NOT Installed OR REINSTALL</Custom>
|
<Custom Action="V170MigrateSettings" After="InstallFiles">NOT Installed OR REINSTALL</Custom>
|
||||||
</InstallExecuteSequence>
|
</InstallExecuteSequence>
|
||||||
|
|
||||||
<InstallUISequence>
|
|
||||||
<Custom Action="JpFindRelatedProducts" After="FindRelatedProducts"/>
|
|
||||||
</InstallUISequence>
|
|
||||||
|
|
||||||
<WixVariable Id="WixUIBannerBmp" Value="$(env.JP_WIXWIZARD_RESOURCES)\banner.bmp" />
|
<WixVariable Id="WixUIBannerBmp" Value="$(env.JP_WIXWIZARD_RESOURCES)\banner.bmp" />
|
||||||
<WixVariable Id="WixUIDialogBmp" Value="$(env.JP_WIXWIZARD_RESOURCES)\background.bmp" />
|
<WixVariable Id="WixUIDialogBmp" Value="$(env.JP_WIXWIZARD_RESOURCES)\background.bmp" />
|
||||||
</Product>
|
</Product>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>org.cryptomator</groupId>
|
<groupId>org.cryptomator</groupId>
|
||||||
<artifactId>cryptomator</artifactId>
|
<artifactId>cryptomator</artifactId>
|
||||||
<version>1.9.1</version>
|
<version>1.9.0-SNAPSHOT</version>
|
||||||
<name>Cryptomator Desktop App</name>
|
<name>Cryptomator Desktop App</name>
|
||||||
|
|
||||||
<organization>
|
<organization>
|
||||||
@@ -26,45 +26,45 @@
|
|||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<project.jdk.version>20</project.jdk.version>
|
<project.jdk.version>19</project.jdk.version>
|
||||||
|
|
||||||
<!-- Group IDs of jars that need to stay on the class path for now -->
|
<!-- Group IDs of jars that need to stay on the class path for now -->
|
||||||
<!-- Once hypfvieh, swiesend, purejava and integrations-linux have module-info, remove them-->
|
<!-- Once hypfvieh, swiesend, purejava and integrations-linux have module-info, remove them-->
|
||||||
<nonModularGroupIds>org.ow2.asm,org.apache.jackrabbit,org.apache.httpcomponents,de.swiesend,org.purejava,com.github.hypfvieh</nonModularGroupIds>
|
<nonModularGroupIds>org.ow2.asm,org.apache.jackrabbit,org.apache.httpcomponents,de.swiesend,org.purejava,com.github.hypfvieh</nonModularGroupIds>
|
||||||
|
|
||||||
<!-- cryptomator dependencies -->
|
<!-- cryptomator dependencies -->
|
||||||
<cryptomator.cryptofs.version>2.6.5</cryptomator.cryptofs.version>
|
<cryptomator.cryptofs.version>2.6.2</cryptomator.cryptofs.version>
|
||||||
<cryptomator.integrations.version>1.2.0</cryptomator.integrations.version>
|
<cryptomator.integrations.version>1.2.0</cryptomator.integrations.version>
|
||||||
<cryptomator.integrations.win.version>1.2.0</cryptomator.integrations.win.version>
|
<cryptomator.integrations.win.version>1.2.0</cryptomator.integrations.win.version>
|
||||||
<cryptomator.integrations.mac.version>1.2.0</cryptomator.integrations.mac.version>
|
<cryptomator.integrations.mac.version>1.2.0</cryptomator.integrations.mac.version>
|
||||||
<cryptomator.integrations.linux.version>1.2.1</cryptomator.integrations.linux.version>
|
<cryptomator.integrations.linux.version>1.2.0</cryptomator.integrations.linux.version>
|
||||||
<cryptomator.fuse.version>3.0.0</cryptomator.fuse.version>
|
<cryptomator.fuse.version>2.0.5</cryptomator.fuse.version>
|
||||||
<cryptomator.dokany.version>2.0.0</cryptomator.dokany.version>
|
<cryptomator.dokany.version>2.0.0</cryptomator.dokany.version>
|
||||||
<cryptomator.webdav.version>2.0.3</cryptomator.webdav.version>
|
<cryptomator.webdav.version>2.0.2</cryptomator.webdav.version>
|
||||||
|
|
||||||
<!-- 3rd party dependencies -->
|
<!-- 3rd party dependencies -->
|
||||||
<commons-lang3.version>3.12.0</commons-lang3.version>
|
<commons-lang3.version>3.12.0</commons-lang3.version>
|
||||||
<dagger.version>2.45</dagger.version>
|
<dagger.version>2.45</dagger.version>
|
||||||
<easybind.version>2.2</easybind.version>
|
<easybind.version>2.2</easybind.version>
|
||||||
<guava.version>32.0.0-jre</guava.version>
|
<guava.version>31.1-jre</guava.version>
|
||||||
<gson.version>2.10.1</gson.version>
|
<gson.version>2.10.1</gson.version>
|
||||||
<javafx.version>20.0.1</javafx.version>
|
<javafx.version>19.0.2.1</javafx.version>
|
||||||
<jwt.version>4.4.0</jwt.version>
|
<jwt.version>4.3.0</jwt.version>
|
||||||
<nimbus-jose.version>9.31</nimbus-jose.version>
|
<nimbus-jose.version>9.31</nimbus-jose.version>
|
||||||
<logback.version>1.4.7</logback.version>
|
<logback.version>1.4.5</logback.version>
|
||||||
<slf4j.version>2.0.7</slf4j.version>
|
<slf4j.version>2.0.6</slf4j.version>
|
||||||
<tinyoauth2.version>0.5.1</tinyoauth2.version>
|
<tinyoauth2.version>0.5.1</tinyoauth2.version>
|
||||||
<zxcvbn.version>1.7.0</zxcvbn.version>
|
<zxcvbn.version>1.7.0</zxcvbn.version>
|
||||||
|
|
||||||
<!-- test dependencies -->
|
<!-- test dependencies -->
|
||||||
<junit.jupiter.version>5.9.3</junit.jupiter.version>
|
<junit.jupiter.version>5.9.2</junit.jupiter.version>
|
||||||
<mockito.version>5.3.1</mockito.version>
|
<mockito.version>5.1.1</mockito.version>
|
||||||
<hamcrest.version>2.2</hamcrest.version>
|
<hamcrest.version>2.2</hamcrest.version>
|
||||||
|
|
||||||
<!-- build-time dependencies -->
|
<!-- build-time dependencies -->
|
||||||
<jetbrains.annotations.version>23.0.0</jetbrains.annotations.version>
|
<jetbrains.annotations.version>23.0.0</jetbrains.annotations.version>
|
||||||
<dependency-check.version>8.1.2</dependency-check.version>
|
<dependency-check.version>8.1.0</dependency-check.version>
|
||||||
<jacoco.version>0.8.9</jacoco.version>
|
<jacoco.version>0.8.8</jacoco.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
@@ -332,9 +332,6 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-surefire-plugin</artifactId>
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
<configuration>
|
|
||||||
<argLine>--enable-preview</argLine>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
</plugin>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
|||||||
@@ -1,16 +1,4 @@
|
|||||||
import ch.qos.logback.classic.spi.Configurator;
|
import ch.qos.logback.classic.spi.Configurator;
|
||||||
import org.cryptomator.common.locationpresets.DropboxLinuxLocationPresetsProvider;
|
|
||||||
import org.cryptomator.common.locationpresets.DropboxMacLocationPresetsProvider;
|
|
||||||
import org.cryptomator.common.locationpresets.DropboxWindowsLocationPresetsProvider;
|
|
||||||
import org.cryptomator.common.locationpresets.GoogleDriveLocationPresetsProvider;
|
|
||||||
import org.cryptomator.common.locationpresets.ICloudMacLocationPresetsProvider;
|
|
||||||
import org.cryptomator.common.locationpresets.ICloudWindowsLocationPresetsProvider;
|
|
||||||
import org.cryptomator.common.locationpresets.LocationPresetsProvider;
|
|
||||||
import org.cryptomator.common.locationpresets.MegaLocationPresetsProvider;
|
|
||||||
import org.cryptomator.common.locationpresets.OneDriveLinuxLocationPresetsProvider;
|
|
||||||
import org.cryptomator.common.locationpresets.OneDriveMacLocationPresetsProvider;
|
|
||||||
import org.cryptomator.common.locationpresets.OneDriveWindowsLocationPresetsProvider;
|
|
||||||
import org.cryptomator.common.locationpresets.PCloudLocationPresetsProvider;
|
|
||||||
import org.cryptomator.integrations.tray.TrayMenuController;
|
import org.cryptomator.integrations.tray.TrayMenuController;
|
||||||
import org.cryptomator.logging.LogbackConfiguratorFactory;
|
import org.cryptomator.logging.LogbackConfiguratorFactory;
|
||||||
import org.cryptomator.ui.traymenu.AwtTrayMenuController;
|
import org.cryptomator.ui.traymenu.AwtTrayMenuController;
|
||||||
@@ -49,15 +37,6 @@ open module org.cryptomator.desktop {
|
|||||||
/* TODO: filename-based modules: */
|
/* TODO: filename-based modules: */
|
||||||
requires static javax.inject; /* ugly dagger/guava crap */
|
requires static javax.inject; /* ugly dagger/guava crap */
|
||||||
|
|
||||||
uses org.cryptomator.common.locationpresets.LocationPresetsProvider;
|
|
||||||
|
|
||||||
provides TrayMenuController with AwtTrayMenuController;
|
provides TrayMenuController with AwtTrayMenuController;
|
||||||
provides Configurator with LogbackConfiguratorFactory;
|
provides Configurator with LogbackConfiguratorFactory;
|
||||||
provides LocationPresetsProvider with DropboxMacLocationPresetsProvider, //
|
|
||||||
DropboxWindowsLocationPresetsProvider, DropboxLinuxLocationPresetsProvider, //
|
|
||||||
ICloudMacLocationPresetsProvider, ICloudWindowsLocationPresetsProvider, //
|
|
||||||
GoogleDriveLocationPresetsProvider, //
|
|
||||||
PCloudLocationPresetsProvider, MegaLocationPresetsProvider, //
|
|
||||||
OneDriveLinuxLocationPresetsProvider, OneDriveWindowsLocationPresetsProvider, //
|
|
||||||
OneDriveMacLocationPresetsProvider;
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
package org.cryptomator.common;
|
||||||
|
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enum of common cloud providers and their default local storage location path.
|
||||||
|
*/
|
||||||
|
public enum LocationPreset {
|
||||||
|
|
||||||
|
DROPBOX("Dropbox", "~/Dropbox"),
|
||||||
|
ICLOUDDRIVE("iCloud Drive", "~/Library/Mobile Documents/com~apple~CloudDocs", "~/iCloudDrive"),
|
||||||
|
GDRIVE("Google Drive", "~/Google Drive/My Drive", "~/Google Drive"),
|
||||||
|
MEGA("MEGA", "~/MEGA"),
|
||||||
|
ONEDRIVE("OneDrive", "~/OneDrive"),
|
||||||
|
PCLOUD("pCloud", "~/pCloudDrive"),
|
||||||
|
|
||||||
|
LOCAL("local");
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
private final List<Path> candidates;
|
||||||
|
|
||||||
|
LocationPreset(String name, String... candidates) {
|
||||||
|
this.name = name;
|
||||||
|
this.candidates = Arrays.stream(candidates).map(UserHome::resolve).map(Path::of).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks for this LocationPreset if any of the associated paths exist.
|
||||||
|
*
|
||||||
|
* @return the first existing path or null, if none exists.
|
||||||
|
*/
|
||||||
|
public Path existingPath() {
|
||||||
|
return candidates.stream().filter(Files::isDirectory).findFirst().orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDisplayName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return getDisplayName();
|
||||||
|
}
|
||||||
|
|
||||||
|
//this contruct is needed, since static members are initialized after every enum member is initialized
|
||||||
|
//TODO: refactor this to normal class and use this also in different parts of the project
|
||||||
|
private static class UserHome {
|
||||||
|
|
||||||
|
private static final String USER_HOME = System.getProperty("user.home");
|
||||||
|
|
||||||
|
private static String resolve(String path) {
|
||||||
|
if (path.startsWith("~/")) {
|
||||||
|
return UserHome.USER_HOME + path.substring(1);
|
||||||
|
} else {
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
-32
@@ -1,32 +0,0 @@
|
|||||||
package org.cryptomator.common.locationpresets;
|
|
||||||
|
|
||||||
import org.cryptomator.integrations.common.OperatingSystem;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.UncheckedIOException;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.util.function.Predicate;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
import static org.cryptomator.integrations.common.OperatingSystem.Value.LINUX;
|
|
||||||
|
|
||||||
@OperatingSystem(LINUX)
|
|
||||||
public final class DropboxLinuxLocationPresetsProvider implements LocationPresetsProvider {
|
|
||||||
|
|
||||||
private static final Path USER_HOME = LocationPresetsProvider.resolveLocation("~/.").toAbsolutePath();
|
|
||||||
private static final Predicate<String> PATTERN = Pattern.compile("Dropbox \\(.+\\)").asMatchPredicate();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Stream<LocationPreset> getLocations() {
|
|
||||||
try (var dirStream = Files.list(USER_HOME)) {
|
|
||||||
var presets = dirStream.filter(p -> Files.isDirectory(p) && PATTERN.test(p.getFileName().toString())) //
|
|
||||||
.map(p -> new LocationPreset(p.getFileName().toString(), p)) //
|
|
||||||
.toList();
|
|
||||||
return presets.stream(); //workaround to ensure that the directory stream is always closed
|
|
||||||
} catch (IOException | UncheckedIOException e) { //UncheckedIOException thrown by the stream of Files.list()
|
|
||||||
return Stream.of();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-35
@@ -1,35 +0,0 @@
|
|||||||
package org.cryptomator.common.locationpresets;
|
|
||||||
|
|
||||||
import org.cryptomator.integrations.common.CheckAvailability;
|
|
||||||
import org.cryptomator.integrations.common.OperatingSystem;
|
|
||||||
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
import static org.cryptomator.integrations.common.OperatingSystem.Value.MAC;
|
|
||||||
|
|
||||||
@OperatingSystem(MAC)
|
|
||||||
@CheckAvailability
|
|
||||||
public final class DropboxMacLocationPresetsProvider implements LocationPresetsProvider {
|
|
||||||
|
|
||||||
private static final Path LOCATION = LocationPresetsProvider.resolveLocation("~/Library/CloudStorage/Dropbox");
|
|
||||||
private static final Path FALLBACK_LOCATION = LocationPresetsProvider.resolveLocation("~/Dropbox");
|
|
||||||
|
|
||||||
|
|
||||||
@CheckAvailability
|
|
||||||
public static boolean isPresent() {
|
|
||||||
return Files.isDirectory(LOCATION) || Files.isDirectory(FALLBACK_LOCATION);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Stream<LocationPreset> getLocations() {
|
|
||||||
if(Files.isDirectory(LOCATION)) {
|
|
||||||
return Stream.of(new LocationPreset("Dropbox", LOCATION));
|
|
||||||
} else if(Files.isDirectory(FALLBACK_LOCATION)) {
|
|
||||||
return Stream.of(new LocationPreset("Dropbox", FALLBACK_LOCATION));
|
|
||||||
} else {
|
|
||||||
return Stream.of();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-28
@@ -1,28 +0,0 @@
|
|||||||
package org.cryptomator.common.locationpresets;
|
|
||||||
|
|
||||||
import org.cryptomator.integrations.common.CheckAvailability;
|
|
||||||
import org.cryptomator.integrations.common.OperatingSystem;
|
|
||||||
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
import static org.cryptomator.integrations.common.OperatingSystem.Value.WINDOWS;
|
|
||||||
|
|
||||||
@OperatingSystem(WINDOWS)
|
|
||||||
@CheckAvailability
|
|
||||||
public final class DropboxWindowsLocationPresetsProvider implements LocationPresetsProvider {
|
|
||||||
|
|
||||||
private static final Path LOCATION = LocationPresetsProvider.resolveLocation("~/Dropbox");
|
|
||||||
|
|
||||||
|
|
||||||
@CheckAvailability
|
|
||||||
public static boolean isPresent() {
|
|
||||||
return Files.isDirectory(LOCATION);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Stream<LocationPreset> getLocations() {
|
|
||||||
return Stream.of(new LocationPreset("Dropbox", LOCATION));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-37
@@ -1,37 +0,0 @@
|
|||||||
package org.cryptomator.common.locationpresets;
|
|
||||||
|
|
||||||
import org.cryptomator.integrations.common.CheckAvailability;
|
|
||||||
import org.cryptomator.integrations.common.OperatingSystem;
|
|
||||||
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
import static org.cryptomator.integrations.common.OperatingSystem.Value.MAC;
|
|
||||||
import static org.cryptomator.integrations.common.OperatingSystem.Value.WINDOWS;
|
|
||||||
|
|
||||||
@OperatingSystem(WINDOWS)
|
|
||||||
@OperatingSystem(MAC)
|
|
||||||
@CheckAvailability
|
|
||||||
public final class GoogleDriveLocationPresetsProvider implements LocationPresetsProvider {
|
|
||||||
|
|
||||||
private static final Path LOCATION1 = LocationPresetsProvider.resolveLocation("~/GoogleDrive");
|
|
||||||
private static final Path LOCATION2 = LocationPresetsProvider.resolveLocation("~/GoogleDrive/My Drive");
|
|
||||||
|
|
||||||
|
|
||||||
@CheckAvailability
|
|
||||||
public static boolean isPresent() {
|
|
||||||
return Files.isDirectory(LOCATION1) || Files.isDirectory(LOCATION2);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Stream<LocationPreset> getLocations() {
|
|
||||||
if(Files.isDirectory(LOCATION1)) {
|
|
||||||
return Stream.of(new LocationPreset("Google Drive", LOCATION1));
|
|
||||||
} else if(Files.isDirectory(LOCATION2)) {
|
|
||||||
return Stream.of(new LocationPreset("Google Drive", LOCATION2));
|
|
||||||
} else {
|
|
||||||
return Stream.of();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-27
@@ -1,27 +0,0 @@
|
|||||||
package org.cryptomator.common.locationpresets;
|
|
||||||
|
|
||||||
import org.cryptomator.integrations.common.CheckAvailability;
|
|
||||||
import org.cryptomator.integrations.common.OperatingSystem;
|
|
||||||
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
import static org.cryptomator.integrations.common.OperatingSystem.Value.MAC;
|
|
||||||
|
|
||||||
@OperatingSystem(MAC)
|
|
||||||
@CheckAvailability
|
|
||||||
public final class ICloudMacLocationPresetsProvider implements LocationPresetsProvider {
|
|
||||||
|
|
||||||
private static final Path LOCATION = LocationPresetsProvider.resolveLocation("~/Library/Mobile Documents/com~apple~CloudDocs");
|
|
||||||
|
|
||||||
@CheckAvailability
|
|
||||||
public static boolean isPresent() {
|
|
||||||
return Files.isDirectory(LOCATION);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Stream<LocationPreset> getLocations() {
|
|
||||||
return Stream.of(new LocationPreset("iCloud Drive", LOCATION));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-27
@@ -1,27 +0,0 @@
|
|||||||
package org.cryptomator.common.locationpresets;
|
|
||||||
|
|
||||||
import org.cryptomator.integrations.common.CheckAvailability;
|
|
||||||
import org.cryptomator.integrations.common.OperatingSystem;
|
|
||||||
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
import static org.cryptomator.integrations.common.OperatingSystem.Value.WINDOWS;
|
|
||||||
|
|
||||||
@OperatingSystem(WINDOWS)
|
|
||||||
@CheckAvailability
|
|
||||||
public final class ICloudWindowsLocationPresetsProvider implements LocationPresetsProvider {
|
|
||||||
|
|
||||||
private static final Path LOCATION = LocationPresetsProvider.resolveLocation("~/iCloudDrive");
|
|
||||||
|
|
||||||
@CheckAvailability
|
|
||||||
public static boolean isPresent() {
|
|
||||||
return Files.isDirectory(LOCATION);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Stream<LocationPreset> getLocations() {
|
|
||||||
return Stream.of(new LocationPreset("iCloud Drive", LOCATION));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
package org.cryptomator.common.locationpresets;
|
|
||||||
|
|
||||||
import java.nio.file.Path;
|
|
||||||
|
|
||||||
public record LocationPreset(String name, Path path) {
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,97 +0,0 @@
|
|||||||
package org.cryptomator.common.locationpresets;
|
|
||||||
|
|
||||||
import org.cryptomator.integrations.common.CheckAvailability;
|
|
||||||
import org.cryptomator.integrations.common.IntegrationsLoader;
|
|
||||||
import org.cryptomator.integrations.common.OperatingSystem;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.lang.reflect.Modifier;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.ServiceLoader;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
public interface LocationPresetsProvider {
|
|
||||||
|
|
||||||
Logger LOG = LoggerFactory.getLogger(LocationPresetsProvider.class);
|
|
||||||
String USER_HOME = System.getProperty("user.home");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Streams account-separated location presets found by this provider
|
|
||||||
* @return Stream of LocationPresets
|
|
||||||
*/
|
|
||||||
Stream<LocationPreset> getLocations();
|
|
||||||
|
|
||||||
static Path resolveLocation(String p) {
|
|
||||||
if (p.startsWith("~/")) {
|
|
||||||
return Path.of(USER_HOME, p.substring(2));
|
|
||||||
} else {
|
|
||||||
return Path.of(p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//copied from org.cryptomator.integrations.common.IntegrationsLoader
|
|
||||||
//TODO: delete, once migrated to integrations-api
|
|
||||||
static <T> Stream<T> loadAll(Class<T> clazz) {
|
|
||||||
return ServiceLoader.load(clazz)
|
|
||||||
.stream()
|
|
||||||
.filter(LocationPresetsProvider::isSupportedOperatingSystem)
|
|
||||||
.filter(LocationPresetsProvider::passesStaticAvailabilityCheck)
|
|
||||||
.map(ServiceLoader.Provider::get)
|
|
||||||
.peek(impl -> logServiceIsAvailable(clazz, impl.getClass()));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private static boolean isSupportedOperatingSystem(ServiceLoader.Provider<?> provider) {
|
|
||||||
var annotations = provider.type().getAnnotationsByType(OperatingSystem.class);
|
|
||||||
return annotations.length == 0 || Arrays.stream(annotations).anyMatch(OperatingSystem.Value::isCurrent);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean passesStaticAvailabilityCheck(ServiceLoader.Provider<?> provider) {
|
|
||||||
return passesStaticAvailabilityCheck(provider.type());
|
|
||||||
}
|
|
||||||
|
|
||||||
static boolean passesStaticAvailabilityCheck(Class<?> type) {
|
|
||||||
return passesAvailabilityCheck(type, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void logServiceIsAvailable(Class<?> apiType, Class<?> implType) {
|
|
||||||
if (LOG.isDebugEnabled()) {
|
|
||||||
LOG.debug("{}: Implementation is available: {}", apiType.getSimpleName(), implType.getName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static <T> boolean passesAvailabilityCheck(Class<? extends T> type, @Nullable T instance) {
|
|
||||||
if (!type.isAnnotationPresent(CheckAvailability.class)) {
|
|
||||||
return true; // if type is not annotated, skip tests
|
|
||||||
}
|
|
||||||
if (!type.getModule().isExported(type.getPackageName(), IntegrationsLoader.class.getModule())) {
|
|
||||||
LOG.error("Can't run @CheckAvailability tests for class {}. Make sure to export {} to {}!", type.getName(), type.getPackageName(), IntegrationsLoader.class.getPackageName());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return Arrays.stream(type.getMethods())
|
|
||||||
.filter(m -> isAvailabilityCheck(m, instance == null))
|
|
||||||
.allMatch(m -> passesAvailabilityCheck(m, instance));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean passesAvailabilityCheck(Method m, @Nullable Object instance) {
|
|
||||||
assert Boolean.TYPE.equals(m.getReturnType());
|
|
||||||
try {
|
|
||||||
return (boolean) m.invoke(instance);
|
|
||||||
} catch (ReflectiveOperationException e) {
|
|
||||||
LOG.warn("Failed to invoke @CheckAvailability test {}#{}", m.getDeclaringClass(), m.getName(), e);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isAvailabilityCheck(Method m, boolean isStatic) {
|
|
||||||
return m.isAnnotationPresent(CheckAvailability.class)
|
|
||||||
&& Boolean.TYPE.equals(m.getReturnType())
|
|
||||||
&& m.getParameterCount() == 0
|
|
||||||
&& Modifier.isStatic(m.getModifiers()) == isStatic;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
package org.cryptomator.common.locationpresets;
|
|
||||||
|
|
||||||
import org.cryptomator.integrations.common.CheckAvailability;
|
|
||||||
import org.cryptomator.integrations.common.OperatingSystem;
|
|
||||||
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
import static org.cryptomator.integrations.common.OperatingSystem.Value.MAC;
|
|
||||||
import static org.cryptomator.integrations.common.OperatingSystem.Value.WINDOWS;
|
|
||||||
|
|
||||||
@OperatingSystem(WINDOWS)
|
|
||||||
@OperatingSystem(MAC)
|
|
||||||
@CheckAvailability
|
|
||||||
public final class MegaLocationPresetsProvider implements LocationPresetsProvider {
|
|
||||||
|
|
||||||
private static final Path LOCATION = LocationPresetsProvider.resolveLocation("~/MEGA");
|
|
||||||
|
|
||||||
@CheckAvailability
|
|
||||||
public static boolean isPresent() {
|
|
||||||
return Files.isDirectory(LOCATION);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Stream<LocationPreset> getLocations() {
|
|
||||||
return Stream.of(new LocationPreset("MEGA", LOCATION));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-28
@@ -1,28 +0,0 @@
|
|||||||
package org.cryptomator.common.locationpresets;
|
|
||||||
|
|
||||||
import org.cryptomator.integrations.common.CheckAvailability;
|
|
||||||
import org.cryptomator.integrations.common.OperatingSystem;
|
|
||||||
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
import static org.cryptomator.integrations.common.OperatingSystem.Value.LINUX;
|
|
||||||
|
|
||||||
@OperatingSystem(LINUX)
|
|
||||||
@CheckAvailability
|
|
||||||
public final class OneDriveLinuxLocationPresetsProvider implements LocationPresetsProvider {
|
|
||||||
|
|
||||||
|
|
||||||
private static final Path LOCATION = LocationPresetsProvider.resolveLocation("~/OneDrive");
|
|
||||||
|
|
||||||
@CheckAvailability
|
|
||||||
public static boolean isPresent() {
|
|
||||||
return Files.isDirectory(LOCATION);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Stream<LocationPreset> getLocations() {
|
|
||||||
return Stream.of(new LocationPreset("OneDrive", LOCATION));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-44
@@ -1,44 +0,0 @@
|
|||||||
package org.cryptomator.common.locationpresets;
|
|
||||||
|
|
||||||
import org.cryptomator.integrations.common.OperatingSystem;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
import java.util.stream.StreamSupport;
|
|
||||||
|
|
||||||
import static org.cryptomator.integrations.common.OperatingSystem.Value.MAC;
|
|
||||||
|
|
||||||
@OperatingSystem(MAC)
|
|
||||||
public final class OneDriveMacLocationPresetsProvider implements LocationPresetsProvider {
|
|
||||||
|
|
||||||
private static final Path FALLBACK_LOCATION = LocationPresetsProvider.resolveLocation("~/OneDrive");
|
|
||||||
private static final Path PARENT_LOCATION = LocationPresetsProvider.resolveLocation("~/Library/CloudStorage");
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Stream<LocationPreset> getLocations() {
|
|
||||||
var newLocations = getNewLocations().toList();
|
|
||||||
if (newLocations.size() >= 1) {
|
|
||||||
return newLocations.stream();
|
|
||||||
} else {
|
|
||||||
return getOldLocation();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Stream<LocationPreset> getNewLocations() {
|
|
||||||
try (var dirStream = Files.newDirectoryStream(PARENT_LOCATION, "OneDrive*")) {
|
|
||||||
return StreamSupport.stream(dirStream.spliterator(), false) //
|
|
||||||
.filter(Files::isDirectory) //
|
|
||||||
.map(p -> new LocationPreset(String.join(" - ", p.getFileName().toString().split("-")), p));
|
|
||||||
} catch (IOException e) {
|
|
||||||
return Stream.of();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Stream<LocationPreset> getOldLocation() {
|
|
||||||
return Stream.of(new LocationPreset("OneDrive", FALLBACK_LOCATION)).filter(preset -> Files.isDirectory(preset.path()));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
-108
@@ -1,108 +0,0 @@
|
|||||||
package org.cryptomator.common.locationpresets;
|
|
||||||
|
|
||||||
import org.cryptomator.integrations.common.OperatingSystem;
|
|
||||||
import org.jetbrains.annotations.Blocking;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.concurrent.TimeoutException;
|
|
||||||
import java.util.function.Predicate;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
import static org.cryptomator.integrations.common.OperatingSystem.Value.WINDOWS;
|
|
||||||
|
|
||||||
@OperatingSystem(WINDOWS)
|
|
||||||
public final class OneDriveWindowsLocationPresetsProvider implements LocationPresetsProvider {
|
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(OneDriveWindowsLocationPresetsProvider.class);
|
|
||||||
private static final String REGSTR_TOKEN = "REG_SZ";
|
|
||||||
private static final String REG_ONEDRIVE_ACCOUNTS = "HKEY_CURRENT_USER\\Software\\Microsoft\\OneDrive\\Accounts\\";
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Stream<LocationPreset> getLocations() {
|
|
||||||
try {
|
|
||||||
var accountRegKeys = queryRegistry(REG_ONEDRIVE_ACCOUNTS, List.of(), l -> l.startsWith(REG_ONEDRIVE_ACCOUNTS)).toList();
|
|
||||||
var cloudLocations = new ArrayList<LocationPreset>();
|
|
||||||
for (var accountRegKey : accountRegKeys) {
|
|
||||||
var path = queryRegistry(accountRegKey, List.of("/v", "UserFolder"), l -> l.contains("UserFolder")).map(result -> result.substring(result.indexOf(REGSTR_TOKEN) + REGSTR_TOKEN.length()).trim()) //
|
|
||||||
.map(Path::of) //
|
|
||||||
.findFirst().orElseThrow();
|
|
||||||
var name = "OneDrive"; //we assume personal oneDrive account by default
|
|
||||||
if (!accountRegKey.endsWith("Personal")) {
|
|
||||||
name = queryRegistry(accountRegKey, List.of("/v", "DisplayName"), l -> l.contains("DisplayName")).map(result -> result.substring(result.indexOf(REGSTR_TOKEN) + REGSTR_TOKEN.length()).trim()) //
|
|
||||||
.map("OneDrive - "::concat) //
|
|
||||||
.findFirst().orElseThrow();
|
|
||||||
}
|
|
||||||
cloudLocations.add(new LocationPreset(name, path));
|
|
||||||
}
|
|
||||||
return cloudLocations.stream();
|
|
||||||
} catch (IOException | CommandFailedException | TimeoutException e) {
|
|
||||||
LOG.error("Unable to determine OneDrive location", e);
|
|
||||||
return Stream.of();
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
Thread.currentThread().interrupt();
|
|
||||||
LOG.error("Determination of OneDrive location interrupted", e);
|
|
||||||
return Stream.of();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Stream<String> queryRegistry(String keyname, List<String> moreArgs, Predicate<String> outputFilter) throws InterruptedException, CommandFailedException, TimeoutException, IOException {
|
|
||||||
var args = new ArrayList<String>();
|
|
||||||
args.add("reg");
|
|
||||||
args.add("query");
|
|
||||||
args.add(keyname);
|
|
||||||
args.addAll(moreArgs);
|
|
||||||
ProcessBuilder command = new ProcessBuilder(args);
|
|
||||||
Process p = command.start();
|
|
||||||
waitForSuccess(p, 3, "`reg query`");
|
|
||||||
return p.inputReader(StandardCharsets.UTF_8).lines().filter(outputFilter);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Waits {@code timeoutSeconds} seconds for {@code process} to finish with exit code {@code 0}.
|
|
||||||
*
|
|
||||||
* @param process The process to wait for
|
|
||||||
* @param timeoutSeconds How long to wait (in seconds)
|
|
||||||
* @param cmdDescription A short description of the process used to generate log and exception messages
|
|
||||||
* @throws TimeoutException Thrown when the process doesn't finish in time
|
|
||||||
* @throws InterruptedException Thrown when the thread is interrupted while waiting for the process to finish
|
|
||||||
* @throws CommandFailedException Thrown when the process exit code is non-zero
|
|
||||||
*/
|
|
||||||
@Blocking
|
|
||||||
private static void waitForSuccess(Process process, int timeoutSeconds, String cmdDescription) throws TimeoutException, InterruptedException, CommandFailedException {
|
|
||||||
boolean exited = process.waitFor(timeoutSeconds, TimeUnit.SECONDS);
|
|
||||||
if (!exited) {
|
|
||||||
throw new TimeoutException(cmdDescription + " timed out after " + timeoutSeconds + "s");
|
|
||||||
}
|
|
||||||
if (process.exitValue() != 0) {
|
|
||||||
@SuppressWarnings("resource") var stdout = process.inputReader(StandardCharsets.UTF_8).lines().collect(Collectors.joining("\n"));
|
|
||||||
@SuppressWarnings("resource") var stderr = process.errorReader(StandardCharsets.UTF_8).lines().collect(Collectors.joining("\n"));
|
|
||||||
throw new CommandFailedException(cmdDescription, process.exitValue(), stdout, stderr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class CommandFailedException extends Exception {
|
|
||||||
|
|
||||||
int exitCode;
|
|
||||||
String stdout;
|
|
||||||
String stderr;
|
|
||||||
|
|
||||||
private CommandFailedException(String cmdDescription, int exitCode, String stdout, String stderr) {
|
|
||||||
super(cmdDescription + " returned with non-zero exit code " + exitCode);
|
|
||||||
this.exitCode = exitCode;
|
|
||||||
this.stdout = stdout;
|
|
||||||
this.stderr = stderr;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
-30
@@ -1,30 +0,0 @@
|
|||||||
package org.cryptomator.common.locationpresets;
|
|
||||||
|
|
||||||
import org.cryptomator.integrations.common.CheckAvailability;
|
|
||||||
import org.cryptomator.integrations.common.OperatingSystem;
|
|
||||||
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
import static org.cryptomator.integrations.common.OperatingSystem.Value.MAC;
|
|
||||||
import static org.cryptomator.integrations.common.OperatingSystem.Value.WINDOWS;
|
|
||||||
|
|
||||||
@OperatingSystem(WINDOWS)
|
|
||||||
@OperatingSystem(MAC)
|
|
||||||
@CheckAvailability
|
|
||||||
public final class PCloudLocationPresetsProvider implements LocationPresetsProvider {
|
|
||||||
|
|
||||||
|
|
||||||
private static final Path LOCATION = LocationPresetsProvider.resolveLocation("~/pCloudDrive");
|
|
||||||
|
|
||||||
@CheckAvailability
|
|
||||||
public static boolean isPresent() {
|
|
||||||
return Files.isDirectory(LOCATION);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Stream<LocationPreset> getLocations() {
|
|
||||||
return Stream.of(new LocationPreset("pCloud", LOCATION));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -9,8 +9,8 @@ import java.nio.channels.ReadableByteChannel;
|
|||||||
import java.nio.channels.WritableByteChannel;
|
import java.nio.channels.WritableByteChannel;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
//TODO can the enum be removed?
|
// TODO make sealed, remove enum
|
||||||
sealed interface IpcMessage permits HandleLaunchArgsMessage, RevealRunningAppMessage {
|
interface IpcMessage {
|
||||||
|
|
||||||
enum MessageType {
|
enum MessageType {
|
||||||
REVEAL_RUNNING_APP(RevealRunningAppMessage::decode),
|
REVEAL_RUNNING_APP(RevealRunningAppMessage::decode),
|
||||||
|
|||||||
@@ -5,9 +5,10 @@ import java.util.List;
|
|||||||
public interface IpcMessageListener {
|
public interface IpcMessageListener {
|
||||||
|
|
||||||
default void handleMessage(IpcMessage message) {
|
default void handleMessage(IpcMessage message) {
|
||||||
switch (message) {
|
if (message instanceof RevealRunningAppMessage) {
|
||||||
case RevealRunningAppMessage m -> revealRunningApp(); // TODO: rename to _ with JEP 443
|
revealRunningApp();
|
||||||
case HandleLaunchArgsMessage m -> handleLaunchArgs(m.args());
|
} else if (message instanceof HandleLaunchArgsMessage m) {
|
||||||
|
handleLaunchArgs(m.args());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,25 +6,27 @@ import org.slf4j.LoggerFactory;
|
|||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.nio.file.FileSystems;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
import java.text.Collator;
|
import java.text.Collator;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.StreamSupport;
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
public class SupportedLanguages {
|
public class SupportedLanguages {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(SupportedLanguages.class);
|
private static final Logger LOG = LoggerFactory.getLogger(SupportedLanguages.class);
|
||||||
// these are BCP 47 language codes, not ISO. Note the "-" instead of the "_".
|
|
||||||
// "en" is not part of this list - it is always inserted at the top.
|
|
||||||
public static final List<String> LANGUAGE_TAGS = List.of("ar", "be", "bn", "bs", "ca", "cs", "da", "de", "el", "es", "fr", "gl", "he", //
|
|
||||||
"hi", "hr", "hu", "id", "it", "ja", "ko", "lv", "nb", "nl", "nn", "pa", "pl", "pt", "pt-BR", "ro", "ru", "sk", "sr", "sr-Latn", "sv", "sw", //
|
|
||||||
"ta", "th", "tr", "uk", "vi", "zh", "zh-HK", "zh-TW");
|
|
||||||
public static final String ENGLISH = "en";
|
public static final String ENGLISH = "en";
|
||||||
|
|
||||||
private final List<String> sortedLanguageTags;
|
private final List<String> sortedLanguageTags;
|
||||||
|
|
||||||
private final Locale preferredLocale;
|
private final Locale preferredLocale;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@@ -33,13 +35,13 @@ public class SupportedLanguages {
|
|||||||
preferredLocale = preferredLanguage == null ? Locale.getDefault() : Locale.forLanguageTag(preferredLanguage);
|
preferredLocale = preferredLanguage == null ? Locale.getDefault() : Locale.forLanguageTag(preferredLanguage);
|
||||||
var collator = Collator.getInstance(preferredLocale);
|
var collator = Collator.getInstance(preferredLocale);
|
||||||
collator.setStrength(Collator.PRIMARY);
|
collator.setStrength(Collator.PRIMARY);
|
||||||
var sorted = new ArrayList<String>();
|
List<String> sortedTags = new ArrayList<>();
|
||||||
sorted.add(0, Settings.DEFAULT_LANGUAGE);
|
sortedTags.add(0, Settings.DEFAULT_LANGUAGE);
|
||||||
sorted.add(1, ENGLISH);
|
sortedTags.add(1, ENGLISH);
|
||||||
LANGUAGE_TAGS.stream() //
|
getSupportedLanguageTags().stream() //
|
||||||
.sorted((a, b) -> collator.compare(Locale.forLanguageTag(a).getDisplayName(), Locale.forLanguageTag(b).getDisplayName())) //
|
.sorted((a, b) -> collator.compare(Locale.forLanguageTag(a).getDisplayName(), Locale.forLanguageTag(b).getDisplayName())) //
|
||||||
.forEach(sorted::add);
|
.forEach(sortedTags::add);
|
||||||
sortedLanguageTags = Collections.unmodifiableList(sorted);
|
sortedLanguageTags = Collections.unmodifiableList(sortedTags);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void applyPreferred() {
|
public void applyPreferred() {
|
||||||
@@ -51,4 +53,43 @@ public class SupportedLanguages {
|
|||||||
return sortedLanguageTags;
|
return sortedLanguageTags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterates over the /i18n directory and extracts from every localization file the BCP 47 code.
|
||||||
|
*
|
||||||
|
* @return list of supported BCP 47 language codes
|
||||||
|
*/
|
||||||
|
private static List<String> getSupportedLanguageTags() {
|
||||||
|
try {
|
||||||
|
var i18DirURI = SupportedLanguages.class.getResource("/i18n").toURI();
|
||||||
|
var uriScheme = i18DirURI.getScheme();
|
||||||
|
if (uriScheme.equals("jar")) {
|
||||||
|
final String[] array = i18DirURI.toString().split("!");
|
||||||
|
try (var jarFs = FileSystems.newFileSystem(URI.create(array[0]), Map.<String, String>of())) {
|
||||||
|
return streamDirectory(jarFs.getPath(array[1]));
|
||||||
|
}
|
||||||
|
} else if (uriScheme.equals("file")) {
|
||||||
|
return streamDirectory(Path.of(i18DirURI));
|
||||||
|
} else {
|
||||||
|
throw new IOException("Unsupported uri scheme: " + uriScheme);
|
||||||
|
}
|
||||||
|
} catch (URISyntaxException | IOException e) {
|
||||||
|
LOG.warn("Unable to determine additional supported languages.", e);
|
||||||
|
return List.of();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<String> streamDirectory(Path i18Dir) throws IOException {
|
||||||
|
try (var dirStream = Files.newDirectoryStream(i18Dir, "strings_*.properties")) {
|
||||||
|
return StreamSupport.stream(dirStream.spliterator(), false) //
|
||||||
|
.map(SupportedLanguages::getBCP47CodeFromFileName) //
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getBCP47CodeFromFileName(Path p) {
|
||||||
|
var fileName = p.getFileName().toString();
|
||||||
|
return fileName.substring("strings_".length(), fileName.indexOf(".properties")).replace('_', '-');
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+84
-63
@@ -1,9 +1,6 @@
|
|||||||
package org.cryptomator.ui.addvaultwizard;
|
package org.cryptomator.ui.addvaultwizard;
|
||||||
|
|
||||||
import dagger.Lazy;
|
import dagger.Lazy;
|
||||||
import org.cryptomator.common.ObservableUtil;
|
|
||||||
import org.cryptomator.common.locationpresets.LocationPreset;
|
|
||||||
import org.cryptomator.common.locationpresets.LocationPresetsProvider;
|
|
||||||
import org.cryptomator.ui.common.FxController;
|
import org.cryptomator.ui.common.FxController;
|
||||||
import org.cryptomator.ui.common.FxmlFile;
|
import org.cryptomator.ui.common.FxmlFile;
|
||||||
import org.cryptomator.ui.common.FxmlScene;
|
import org.cryptomator.ui.common.FxmlScene;
|
||||||
@@ -13,19 +10,22 @@ import org.slf4j.LoggerFactory;
|
|||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
|
import javafx.beans.binding.Bindings;
|
||||||
import javafx.beans.binding.BooleanBinding;
|
import javafx.beans.binding.BooleanBinding;
|
||||||
import javafx.beans.property.BooleanProperty;
|
import javafx.beans.property.BooleanProperty;
|
||||||
import javafx.beans.property.ObjectProperty;
|
import javafx.beans.property.ObjectProperty;
|
||||||
import javafx.beans.property.SimpleBooleanProperty;
|
import javafx.beans.property.SimpleBooleanProperty;
|
||||||
|
import javafx.beans.property.SimpleObjectProperty;
|
||||||
|
import javafx.beans.property.SimpleStringProperty;
|
||||||
import javafx.beans.property.StringProperty;
|
import javafx.beans.property.StringProperty;
|
||||||
import javafx.beans.value.ObservableValue;
|
import javafx.beans.value.ObservableValue;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
|
import javafx.scene.Node;
|
||||||
import javafx.scene.Scene;
|
import javafx.scene.Scene;
|
||||||
import javafx.scene.control.Label;
|
import javafx.scene.control.Label;
|
||||||
import javafx.scene.control.RadioButton;
|
import javafx.scene.control.RadioButton;
|
||||||
import javafx.scene.control.Toggle;
|
import javafx.scene.control.Toggle;
|
||||||
import javafx.scene.control.ToggleGroup;
|
import javafx.scene.control.ToggleGroup;
|
||||||
import javafx.scene.layout.VBox;
|
|
||||||
import javafx.stage.DirectoryChooser;
|
import javafx.stage.DirectoryChooser;
|
||||||
import javafx.stage.Stage;
|
import javafx.stage.Stage;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@@ -34,9 +34,6 @@ import java.nio.file.Files;
|
|||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.nio.file.StandardOpenOption;
|
import java.nio.file.StandardOpenOption;
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.ResourceBundle;
|
import java.util.ResourceBundle;
|
||||||
|
|
||||||
@AddVaultWizardScoped
|
@AddVaultWizardScoped
|
||||||
@@ -49,72 +46,70 @@ public class CreateNewVaultLocationController implements FxController {
|
|||||||
private final Stage window;
|
private final Stage window;
|
||||||
private final Lazy<Scene> chooseNameScene;
|
private final Lazy<Scene> chooseNameScene;
|
||||||
private final Lazy<Scene> choosePasswordScene;
|
private final Lazy<Scene> choosePasswordScene;
|
||||||
private final List<RadioButton> locationPresetBtns;
|
private final ObservedLocationPresets locationPresets;
|
||||||
private final ObjectProperty<Path> vaultPath;
|
private final ObjectProperty<Path> vaultPath;
|
||||||
private final StringProperty vaultName;
|
private final StringProperty vaultName;
|
||||||
private final ResourceBundle resourceBundle;
|
private final ResourceBundle resourceBundle;
|
||||||
private final ObservableValue<VaultPathStatus> vaultPathStatus;
|
private final BooleanBinding validVaultPath;
|
||||||
private final ObservableValue<Boolean> validVaultPath;
|
|
||||||
private final BooleanProperty usePresetPath;
|
private final BooleanProperty usePresetPath;
|
||||||
|
private final StringProperty statusText;
|
||||||
|
private final ObjectProperty<Node> statusGraphic;
|
||||||
|
|
||||||
private Path customVaultPath = DEFAULT_CUSTOM_VAULT_PATH;
|
private Path customVaultPath = DEFAULT_CUSTOM_VAULT_PATH;
|
||||||
|
|
||||||
//FXML
|
//FXML
|
||||||
public ToggleGroup locationPresetsToggler;
|
public ToggleGroup predefinedLocationToggler;
|
||||||
public VBox radioButtonVBox;
|
public RadioButton iclouddriveRadioButton;
|
||||||
|
public RadioButton dropboxRadioButton;
|
||||||
|
public RadioButton gdriveRadioButton;
|
||||||
|
public RadioButton onedriveRadioButton;
|
||||||
|
public RadioButton megaRadioButton;
|
||||||
|
public RadioButton pcloudRadioButton;
|
||||||
public RadioButton customRadioButton;
|
public RadioButton customRadioButton;
|
||||||
public Label locationStatusLabel;
|
public Label vaultPathStatus;
|
||||||
public FontAwesome5IconView goodLocation;
|
public FontAwesome5IconView goodLocation;
|
||||||
public FontAwesome5IconView badLocation;
|
public FontAwesome5IconView badLocation;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
CreateNewVaultLocationController(@AddVaultWizardWindow Stage window, @FxmlScene(FxmlFile.ADDVAULT_NEW_NAME) Lazy<Scene> chooseNameScene, @FxmlScene(FxmlFile.ADDVAULT_NEW_PASSWORD) Lazy<Scene> choosePasswordScene, 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, ObservedLocationPresets locationPresets, ObjectProperty<Path> vaultPath, @Named("vaultName") StringProperty vaultName, ResourceBundle resourceBundle) {
|
||||||
this.window = window;
|
this.window = window;
|
||||||
this.chooseNameScene = chooseNameScene;
|
this.chooseNameScene = chooseNameScene;
|
||||||
this.choosePasswordScene = choosePasswordScene;
|
this.choosePasswordScene = choosePasswordScene;
|
||||||
|
this.locationPresets = locationPresets;
|
||||||
this.vaultPath = vaultPath;
|
this.vaultPath = vaultPath;
|
||||||
this.vaultName = vaultName;
|
this.vaultName = vaultName;
|
||||||
this.resourceBundle = resourceBundle;
|
this.resourceBundle = resourceBundle;
|
||||||
this.vaultPathStatus = ObservableUtil.mapWithDefault(vaultPath, this::validatePath, new VaultPathStatus(false, "error.message"));
|
this.validVaultPath = Bindings.createBooleanBinding(this::validateVaultPathAndSetStatus, this.vaultPath);
|
||||||
this.validVaultPath = ObservableUtil.mapWithDefault(vaultPathStatus, VaultPathStatus::valid, false);
|
|
||||||
this.vaultPathStatus.addListener(this::updateStatusLabel);
|
|
||||||
this.usePresetPath = new SimpleBooleanProperty();
|
this.usePresetPath = new SimpleBooleanProperty();
|
||||||
this.locationPresetBtns = LocationPresetsProvider.loadAll(LocationPresetsProvider.class) //
|
this.statusText = new SimpleStringProperty();
|
||||||
.flatMap(LocationPresetsProvider::getLocations) //
|
this.statusGraphic = new SimpleObjectProperty<>();
|
||||||
.sorted(Comparator.comparing(LocationPreset::name)) //
|
|
||||||
.map(preset -> { //
|
|
||||||
var btn = new RadioButton(preset.name());
|
|
||||||
btn.setUserData(preset.path());
|
|
||||||
return btn;
|
|
||||||
}).toList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private VaultPathStatus validatePath(Path p) throws NullPointerException {
|
private boolean validateVaultPathAndSetStatus() {
|
||||||
if (!Files.exists(p.getParent())) {
|
final Path p = vaultPath.get();
|
||||||
return new VaultPathStatus(false, "addvaultwizard.new.locationDoesNotExist");
|
if (p == null) {
|
||||||
|
statusText.set("Error: Path is NULL.");
|
||||||
|
statusGraphic.set(badLocation);
|
||||||
|
return false;
|
||||||
|
} else if (!Files.exists(p.getParent())) {
|
||||||
|
statusText.set(resourceBundle.getString("addvaultwizard.new.locationDoesNotExist"));
|
||||||
|
statusGraphic.set(badLocation);
|
||||||
|
return false;
|
||||||
} else if (!isActuallyWritable(p.getParent())) {
|
} else if (!isActuallyWritable(p.getParent())) {
|
||||||
return new VaultPathStatus(false, "addvaultwizard.new.locationIsNotWritable");
|
statusText.set(resourceBundle.getString("addvaultwizard.new.locationIsNotWritable"));
|
||||||
|
statusGraphic.set(badLocation);
|
||||||
|
return false;
|
||||||
} else if (!Files.notExists(p)) {
|
} else if (!Files.notExists(p)) {
|
||||||
return new VaultPathStatus(false, "addvaultwizard.new.fileAlreadyExists");
|
statusText.set(resourceBundle.getString("addvaultwizard.new.fileAlreadyExists"));
|
||||||
|
statusGraphic.set(badLocation);
|
||||||
|
return false;
|
||||||
} else {
|
} else {
|
||||||
return new VaultPathStatus(true, "addvaultwizard.new.locationIsOk");
|
statusText.set(resourceBundle.getString("addvaultwizard.new.locationIsOk"));
|
||||||
|
statusGraphic.set(goodLocation);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateStatusLabel(ObservableValue<? extends VaultPathStatus> observable, VaultPathStatus oldValue, VaultPathStatus newValue) {
|
|
||||||
if (newValue.valid()) {
|
|
||||||
locationStatusLabel.setGraphic(goodLocation);
|
|
||||||
locationStatusLabel.getStyleClass().remove("label-red");
|
|
||||||
locationStatusLabel.getStyleClass().add("label-muted");
|
|
||||||
} else {
|
|
||||||
locationStatusLabel.setGraphic(badLocation);
|
|
||||||
locationStatusLabel.getStyleClass().remove("label-muted");
|
|
||||||
locationStatusLabel.getStyleClass().add("label-red");
|
|
||||||
}
|
|
||||||
this.locationStatusLabel.setText(resourceBundle.getString(newValue.localizationKey()));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private boolean isActuallyWritable(Path p) {
|
private boolean isActuallyWritable(Path p) {
|
||||||
Path tmpFile = p.resolve(TEMP_FILE_FORMAT);
|
Path tmpFile = p.resolve(TEMP_FILE_FORMAT);
|
||||||
try (var chan = Files.newByteChannel(tmpFile, StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE, StandardOpenOption.DELETE_ON_CLOSE)) {
|
try (var chan = Files.newByteChannel(tmpFile, StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE, StandardOpenOption.DELETE_ON_CLOSE)) {
|
||||||
@@ -132,15 +127,26 @@ public class CreateNewVaultLocationController implements FxController {
|
|||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
public void initialize() {
|
public void initialize() {
|
||||||
radioButtonVBox.getChildren().addAll(1, locationPresetBtns); //first item is the list header
|
predefinedLocationToggler.selectedToggleProperty().addListener(this::togglePredefinedLocation);
|
||||||
locationPresetsToggler.getToggles().addAll(locationPresetBtns);
|
usePresetPath.bind(predefinedLocationToggler.selectedToggleProperty().isNotEqualTo(customRadioButton));
|
||||||
locationPresetsToggler.selectedToggleProperty().addListener(this::togglePredefinedLocation);
|
|
||||||
usePresetPath.bind(locationPresetsToggler.selectedToggleProperty().isNotEqualTo(customRadioButton));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void togglePredefinedLocation(@SuppressWarnings("unused") ObservableValue<? extends Toggle> observable, @SuppressWarnings("unused") Toggle oldValue, Toggle newValue) {
|
private void togglePredefinedLocation(@SuppressWarnings("unused") ObservableValue<? extends Toggle> observable, @SuppressWarnings("unused") Toggle oldValue, Toggle newValue) {
|
||||||
var storagePath = Optional.ofNullable((Path) newValue.getUserData()).orElse(customVaultPath);
|
if (iclouddriveRadioButton.equals(newValue)) {
|
||||||
vaultPath.set(storagePath.resolve(vaultName.get()));
|
vaultPath.set(locationPresets.getIclouddriveLocation().resolve(vaultName.get()));
|
||||||
|
} else if (dropboxRadioButton.equals(newValue)) {
|
||||||
|
vaultPath.set(locationPresets.getDropboxLocation().resolve(vaultName.get()));
|
||||||
|
} else if (gdriveRadioButton.equals(newValue)) {
|
||||||
|
vaultPath.set(locationPresets.getGdriveLocation().resolve(vaultName.get()));
|
||||||
|
} else if (onedriveRadioButton.equals(newValue)) {
|
||||||
|
vaultPath.set(locationPresets.getOnedriveLocation().resolve(vaultName.get()));
|
||||||
|
} else if (megaRadioButton.equals(newValue)) {
|
||||||
|
vaultPath.set(locationPresets.getMegaLocation().resolve(vaultName.get()));
|
||||||
|
} else if (pcloudRadioButton.equals(newValue)) {
|
||||||
|
vaultPath.set(locationPresets.getPcloudLocation().resolve(vaultName.get()));
|
||||||
|
} else if (customRadioButton.equals(newValue)) {
|
||||||
|
vaultPath.set(customVaultPath.resolve(vaultName.get()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
@@ -150,8 +156,10 @@ public class CreateNewVaultLocationController implements FxController {
|
|||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
public void next() {
|
public void next() {
|
||||||
if (validVaultPath.getValue()) {
|
if (validateVaultPathAndSetStatus()) {
|
||||||
window.setScene(choosePasswordScene.get());
|
window.setScene(choosePasswordScene.get());
|
||||||
|
} else {
|
||||||
|
validVaultPath.invalidate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,12 +179,6 @@ public class CreateNewVaultLocationController implements FxController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Internal classes */
|
|
||||||
|
|
||||||
private record VaultPathStatus(boolean valid, String localizationKey) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Getter/Setter */
|
/* Getter/Setter */
|
||||||
|
|
||||||
public Path getVaultPath() {
|
public Path getVaultPath() {
|
||||||
@@ -187,28 +189,47 @@ public class CreateNewVaultLocationController implements FxController {
|
|||||||
return vaultPath;
|
return vaultPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ObservableValue<Boolean> validVaultPathProperty() {
|
public BooleanBinding validVaultPathProperty() {
|
||||||
return validVaultPath;
|
return validVaultPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isValidVaultPath() {
|
public Boolean getValidVaultPath() {
|
||||||
return validVaultPath.getValue();
|
return validVaultPath.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ObservedLocationPresets getObservedLocationPresets() {
|
||||||
|
return locationPresets;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BooleanProperty usePresetPathProperty() {
|
public BooleanProperty usePresetPathProperty() {
|
||||||
return usePresetPath;
|
return usePresetPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isUsePresetPath() {
|
public boolean getUsePresetPath() {
|
||||||
return usePresetPath.get();
|
return usePresetPath.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
public BooleanBinding anyRadioButtonSelectedProperty() {
|
public BooleanBinding anyRadioButtonSelectedProperty() {
|
||||||
return locationPresetsToggler.selectedToggleProperty().isNotNull();
|
return predefinedLocationToggler.selectedToggleProperty().isNotNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isAnyRadioButtonSelected() {
|
public boolean isAnyRadioButtonSelected() {
|
||||||
return anyRadioButtonSelectedProperty().get();
|
return anyRadioButtonSelectedProperty().get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public StringProperty statusTextProperty() {
|
||||||
|
return statusText;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStatusText() {
|
||||||
|
return statusText.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ObjectProperty<Node> statusGraphicProperty() {
|
||||||
|
return statusGraphic;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Node getStatusGraphic() {
|
||||||
|
return statusGraphic.get();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,141 @@
|
|||||||
|
package org.cryptomator.ui.addvaultwizard;
|
||||||
|
|
||||||
|
import org.cryptomator.common.LocationPreset;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javafx.beans.binding.BooleanBinding;
|
||||||
|
import javafx.beans.property.ReadOnlyObjectProperty;
|
||||||
|
import javafx.beans.property.SimpleObjectProperty;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
|
||||||
|
@AddVaultWizardScoped
|
||||||
|
public class ObservedLocationPresets {
|
||||||
|
|
||||||
|
private final ReadOnlyObjectProperty<Path> iclouddriveLocation;
|
||||||
|
private final ReadOnlyObjectProperty<Path> dropboxLocation;
|
||||||
|
private final ReadOnlyObjectProperty<Path> gdriveLocation;
|
||||||
|
private final ReadOnlyObjectProperty<Path> onedriveLocation;
|
||||||
|
private final ReadOnlyObjectProperty<Path> megaLocation;
|
||||||
|
private final ReadOnlyObjectProperty<Path> pcloudLocation;
|
||||||
|
private final BooleanBinding foundIclouddrive;
|
||||||
|
private final BooleanBinding foundDropbox;
|
||||||
|
private final BooleanBinding foundGdrive;
|
||||||
|
private final BooleanBinding foundOnedrive;
|
||||||
|
private final BooleanBinding foundMega;
|
||||||
|
private final BooleanBinding foundPcloud;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public ObservedLocationPresets() {
|
||||||
|
this.iclouddriveLocation = new SimpleObjectProperty<>(LocationPreset.ICLOUDDRIVE.existingPath());
|
||||||
|
this.dropboxLocation = new SimpleObjectProperty<>(LocationPreset.DROPBOX.existingPath());
|
||||||
|
this.gdriveLocation = new SimpleObjectProperty<>(LocationPreset.GDRIVE.existingPath());
|
||||||
|
this.onedriveLocation = new SimpleObjectProperty<>(LocationPreset.ONEDRIVE.existingPath());
|
||||||
|
this.megaLocation = new SimpleObjectProperty<>(LocationPreset.MEGA.existingPath());
|
||||||
|
this.pcloudLocation = new SimpleObjectProperty<>(LocationPreset.PCLOUD.existingPath());
|
||||||
|
this.foundIclouddrive = iclouddriveLocation.isNotNull();
|
||||||
|
this.foundDropbox = dropboxLocation.isNotNull();
|
||||||
|
this.foundGdrive = gdriveLocation.isNotNull();
|
||||||
|
this.foundOnedrive = onedriveLocation.isNotNull();
|
||||||
|
this.foundMega = megaLocation.isNotNull();
|
||||||
|
this.foundPcloud = pcloudLocation.isNotNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Observables */
|
||||||
|
|
||||||
|
public ReadOnlyObjectProperty<Path> iclouddriveLocationProperty() {
|
||||||
|
return iclouddriveLocation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Path getIclouddriveLocation() {
|
||||||
|
return iclouddriveLocation.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public BooleanBinding foundIclouddriveProperty() {
|
||||||
|
return foundIclouddrive;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isFoundIclouddrive() {
|
||||||
|
return foundIclouddrive.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReadOnlyObjectProperty<Path> dropboxLocationProperty() {
|
||||||
|
return dropboxLocation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Path getDropboxLocation() {
|
||||||
|
return dropboxLocation.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public BooleanBinding foundDropboxProperty() {
|
||||||
|
return foundDropbox;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isFoundDropbox() {
|
||||||
|
return foundDropbox.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReadOnlyObjectProperty<Path> gdriveLocationProperty() {
|
||||||
|
return gdriveLocation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Path getGdriveLocation() {
|
||||||
|
return gdriveLocation.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public BooleanBinding foundGdriveProperty() {
|
||||||
|
return foundGdrive;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isFoundGdrive() {
|
||||||
|
return foundGdrive.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReadOnlyObjectProperty<Path> onedriveLocationProperty() {
|
||||||
|
return onedriveLocation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Path getOnedriveLocation() {
|
||||||
|
return onedriveLocation.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public BooleanBinding foundOnedriveProperty() {
|
||||||
|
return foundOnedrive;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isFoundOnedrive() {
|
||||||
|
return foundOnedrive.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReadOnlyObjectProperty<Path> megaLocationProperty() {
|
||||||
|
return megaLocation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Path getMegaLocation() {
|
||||||
|
return megaLocation.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public BooleanBinding foundMegaProperty() {
|
||||||
|
return foundMega;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isFoundMega() {
|
||||||
|
return foundMega.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReadOnlyObjectProperty<Path> pcloudLocationProperty() {
|
||||||
|
return pcloudLocation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Path getPcloudLocation() {
|
||||||
|
return pcloudLocation.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public BooleanBinding foundPcloudProperty() {
|
||||||
|
return foundPcloud;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isFoundPcloud() {
|
||||||
|
return foundPcloud.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,85 +1,30 @@
|
|||||||
package org.cryptomator.ui.fxapp;
|
package org.cryptomator.ui.fxapp;
|
||||||
|
|
||||||
import org.cryptomator.common.vaults.Vault;
|
import org.cryptomator.common.vaults.Vault;
|
||||||
import org.cryptomator.common.vaults.VaultListManager;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javafx.collections.ObservableList;
|
import javafx.collections.ObservableList;
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.CompletionStage;
|
import java.util.concurrent.CompletionStage;
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
|
||||||
import java.util.concurrent.ScheduledFuture;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.function.Predicate;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
@FxApplicationScoped
|
@FxApplicationScoped
|
||||||
public class AutoUnlocker {
|
public class AutoUnlocker {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(AutoUnlocker.class);
|
|
||||||
|
|
||||||
private final ObservableList<Vault> vaults;
|
private final ObservableList<Vault> vaults;
|
||||||
private final FxApplicationWindows appWindows;
|
private final FxApplicationWindows appWindows;
|
||||||
private final ScheduledExecutorService scheduler;
|
|
||||||
private ScheduledFuture<?> unlockMissingFuture;
|
|
||||||
private ScheduledFuture<?> timeoutFuture;
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public AutoUnlocker(ObservableList<Vault> vaults, FxApplicationWindows appWindows, ScheduledExecutorService scheduler) {
|
public AutoUnlocker(ObservableList<Vault> vaults, FxApplicationWindows appWindows) {
|
||||||
this.vaults = vaults;
|
this.vaults = vaults;
|
||||||
this.appWindows = appWindows;
|
this.appWindows = appWindows;
|
||||||
this.scheduler = scheduler;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void tryUnlockForTimespan(int timespan, TimeUnit timeUnit) {
|
public void unlock() {
|
||||||
// Unlock all available auto unlock vaults
|
vaults.stream().filter(Vault::isLocked) //
|
||||||
Predicate<Vault> shouldAutoUnlock = v -> v.getVaultSettings().unlockAfterStartup().get();
|
.filter(v -> v.getVaultSettings().unlockAfterStartup().get()) //
|
||||||
unlockSequentially(vaults.stream().filter(shouldAutoUnlock)).thenRun(() -> startUnlockMissing(timespan, timeUnit));
|
.<CompletionStage<Void>>reduce(CompletableFuture.completedFuture(null), //
|
||||||
|
(unlockFlow, v) -> unlockFlow.handle((voit, ex) -> appWindows.startUnlockWorkflow(v, null)).thenCompose(stage -> stage), //we don't care here about the exception, logged elsewhere
|
||||||
|
(unlockChain1, unlockChain2) -> unlockChain1.handle((voit, ex) -> unlockChain2).thenCompose(stage -> stage));
|
||||||
}
|
}
|
||||||
|
|
||||||
private CompletionStage<Void> unlockSequentially(Stream<Vault> vaultStream) {
|
|
||||||
// this is an attempt to run all the unlock workflows sequentially, i.e. start the next workflow only after completing/failing the previous workflow.
|
|
||||||
return vaultStream.filter(Vault::isLocked).reduce(CompletableFuture.completedFuture(null),
|
|
||||||
(prevUnlock, nextVault) -> prevUnlock.thenCompose(unused -> appWindows.startUnlockWorkflow(nextVault, null)),
|
|
||||||
(prevUnlock, nextUnlock) -> nextUnlock.exceptionally(e -> null) // we don't care here about the exception, logged elsewhere
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void startUnlockMissing(int timespan, TimeUnit timeUnit) {
|
|
||||||
// Start a temporary service if there are missing auto unlock vaults
|
|
||||||
if (getMissingAutoUnlockVaults().findAny().isPresent()) {
|
|
||||||
LOG.info("Found MISSING vaults, starting periodic check");
|
|
||||||
unlockMissingFuture = scheduler.scheduleWithFixedDelay(this::unlockMissing, 0, 1, TimeUnit.SECONDS);
|
|
||||||
timeoutFuture = scheduler.schedule(this::timeout, timespan, timeUnit);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void unlockMissing() {
|
|
||||||
List<Vault> missingAutoUnlockVaults = getMissingAutoUnlockVaults().toList();
|
|
||||||
missingAutoUnlockVaults.forEach(VaultListManager::redetermineVaultState);
|
|
||||||
unlockSequentially(missingAutoUnlockVaults.stream()).thenRun(this::stopUnlockMissing);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void stopUnlockMissing() {
|
|
||||||
// Stop checking if there are no more missing vaults
|
|
||||||
if (getMissingAutoUnlockVaults().findAny().isEmpty()) {
|
|
||||||
LOG.info("No more MISSING vaults, stopping periodic check");
|
|
||||||
unlockMissingFuture.cancel(false);
|
|
||||||
timeoutFuture.cancel(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void timeout() {
|
|
||||||
LOG.info("MISSING vaults periodic check timed out");
|
|
||||||
unlockMissingFuture.cancel(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Stream<Vault> getMissingAutoUnlockVaults() {
|
|
||||||
return vaults.stream()
|
|
||||||
.filter(Vault::isMissing)
|
|
||||||
.filter(v -> v.getVaultSettings().unlockAfterStartup().get());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import org.slf4j.LoggerFactory;
|
|||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
@FxApplicationScoped
|
@FxApplicationScoped
|
||||||
public class FxApplication {
|
public class FxApplication {
|
||||||
@@ -69,6 +68,7 @@ public class FxApplication {
|
|||||||
});
|
});
|
||||||
|
|
||||||
launchEventHandler.startHandlingLaunchEvents();
|
launchEventHandler.startHandlingLaunchEvents();
|
||||||
autoUnlocker.tryUnlockForTimespan(2, TimeUnit.MINUTES);
|
autoUnlocker.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import org.cryptomator.ui.preferences.PreferencesComponent;
|
|||||||
import org.cryptomator.ui.preferences.SelectedPreferencesTab;
|
import org.cryptomator.ui.preferences.SelectedPreferencesTab;
|
||||||
import org.cryptomator.ui.quit.QuitComponent;
|
import org.cryptomator.ui.quit.QuitComponent;
|
||||||
import org.cryptomator.ui.unlock.UnlockComponent;
|
import org.cryptomator.ui.unlock.UnlockComponent;
|
||||||
import org.cryptomator.ui.unlock.UnlockWorkflow;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -115,7 +114,7 @@ public class FxApplicationWindows {
|
|||||||
LOG.debug("Start unlock workflow for {}", vault.getDisplayName());
|
LOG.debug("Start unlock workflow for {}", vault.getDisplayName());
|
||||||
return unlockWorkflowFactory.create(vault, owner).unlockWorkflow();
|
return unlockWorkflowFactory.create(vault, owner).unlockWorkflow();
|
||||||
}, Platform::runLater) //
|
}, Platform::runLater) //
|
||||||
.thenAcceptAsync(UnlockWorkflow::run, executor)
|
.thenCompose(unlockWorkflow -> CompletableFuture.runAsync(unlockWorkflow, executor)) //
|
||||||
.exceptionally(e -> {
|
.exceptionally(e -> {
|
||||||
showErrorWindow(e, owner == null ? primaryStage : owner, null);
|
showErrorWindow(e, owner == null ? primaryStage : owner, null);
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -102,16 +102,14 @@ public class StartController implements FxController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void loadingKeyFailed(Throwable e) {
|
private void loadingKeyFailed(Throwable e) {
|
||||||
switch (e) {
|
if (e instanceof UnlockCancelledException) {
|
||||||
case UnlockCancelledException uce -> {} //ok
|
// ok
|
||||||
case VaultKeyInvalidException vkie -> {
|
} else if (e instanceof VaultKeyInvalidException) {
|
||||||
LOG.error("Invalid key"); //TODO: specific error screen
|
LOG.error("Invalid key"); //TODO: specific error screen
|
||||||
appWindows.showErrorWindow(e, window, null);
|
appWindows.showErrorWindow(e, window, null);
|
||||||
}
|
} else {
|
||||||
default -> {
|
LOG.error("Failed to load key.", e);
|
||||||
LOG.error("Failed to load key.", e);
|
appWindows.showErrorWindow(e, window, null);
|
||||||
appWindows.showErrorWindow(e, window, null);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -84,19 +84,18 @@ public class AwtTrayMenuController implements TrayMenuController {
|
|||||||
|
|
||||||
private void addChildren(Menu menu, List<TrayMenuItem> items) {
|
private void addChildren(Menu menu, List<TrayMenuItem> items) {
|
||||||
for (var item : items) {
|
for (var item : items) {
|
||||||
switch (item) {
|
// TODO: use Pattern Matching for switch, once available
|
||||||
case ActionItem a -> {
|
if (item instanceof ActionItem a) {
|
||||||
var menuItem = new MenuItem(a.title());
|
var menuItem = new MenuItem(a.title());
|
||||||
menuItem.addActionListener(evt -> a.action().run());
|
menuItem.addActionListener(evt -> a.action().run());
|
||||||
menuItem.setEnabled(a.enabled());
|
menuItem.setEnabled(a.enabled());
|
||||||
menu.add(menuItem);
|
menu.add(menuItem);
|
||||||
}
|
} else if (item instanceof SeparatorItem) {
|
||||||
case SeparatorItem s -> menu.addSeparator(); // TODO: rename to _ with JEP 443
|
menu.addSeparator();
|
||||||
case SubMenuItem s -> {
|
} else if (item instanceof SubMenuItem s) {
|
||||||
var submenu = new Menu(s.title());
|
var submenu = new Menu(s.title());
|
||||||
addChildren(submenu, s.items());
|
addChildren(submenu, s.items());
|
||||||
menu.add(submenu);
|
menu.add(submenu);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,11 +38,12 @@ public class UnlockInvalidMountPointController implements FxController {
|
|||||||
@FXML
|
@FXML
|
||||||
public void initialize() {
|
public void initialize() {
|
||||||
var e = unlockException.get();
|
var e = unlockException.get();
|
||||||
var translationKey = switch (e) {
|
String translationKey = "unlock.error.customPath.description.generic";
|
||||||
case MountPointNotSupportedException x -> "unlock.error.customPath.description.notSupported";
|
if (e instanceof MountPointNotSupportedException) {
|
||||||
case MountPointNotExistsException x -> "unlock.error.customPath.description.notExists";
|
translationKey = "unlock.error.customPath.description.notSupported";
|
||||||
default -> "unlock.error.customPath.description.generic";
|
} else if (e instanceof MountPointNotExistsException) {
|
||||||
};
|
translationKey = "unlock.error.customPath.description.notExists";
|
||||||
|
}
|
||||||
dialogDescription.setFormat(resourceBundle.getString(translationKey));
|
dialogDescription.setFormat(resourceBundle.getString(translationKey));
|
||||||
dialogDescription.setArg1(e.getMessage());
|
dialogDescription.setArg1(e.getMessage());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
spacing="12"
|
spacing="12"
|
||||||
alignment="CENTER_LEFT">
|
alignment="CENTER_LEFT">
|
||||||
<fx:define>
|
<fx:define>
|
||||||
<ToggleGroup fx:id="locationPresetsToggler"/>
|
<ToggleGroup fx:id="predefinedLocationToggler"/>
|
||||||
<FontAwesome5IconView fx:id="badLocation" styleClass="glyph-icon-red" glyph="TIMES" />
|
<FontAwesome5IconView fx:id="badLocation" styleClass="glyph-icon-red" glyph="TIMES" />
|
||||||
<FontAwesome5IconView fx:id="goodLocation" styleClass="glyph-icon-primary" glyph="CHECK" />
|
<FontAwesome5IconView fx:id="goodLocation" styleClass="glyph-icon-primary" glyph="CHECK" />
|
||||||
</fx:define>
|
</fx:define>
|
||||||
@@ -29,11 +29,16 @@
|
|||||||
<children>
|
<children>
|
||||||
<Region VBox.vgrow="ALWAYS"/>
|
<Region VBox.vgrow="ALWAYS"/>
|
||||||
|
|
||||||
<VBox fx:id="radioButtonVBox" spacing="6">
|
<VBox spacing="6">
|
||||||
<Label wrapText="true" text="%addvaultwizard.new.locationInstruction"/>
|
<Label wrapText="true" text="%addvaultwizard.new.locationInstruction"/>
|
||||||
<!-- PLACEHOLDER, more radio buttons are added programmatically via controller -->
|
<RadioButton fx:id="iclouddriveRadioButton" toggleGroup="${predefinedLocationToggler}" text="iCloud Drive" visible="${controller.observedLocationPresets.foundIclouddrive}" managed="${controller.observedLocationPresets.foundIclouddrive}"/>
|
||||||
|
<RadioButton fx:id="dropboxRadioButton" toggleGroup="${predefinedLocationToggler}" text="Dropbox" visible="${controller.observedLocationPresets.foundDropbox}" managed="${controller.observedLocationPresets.foundDropbox}"/>
|
||||||
|
<RadioButton fx:id="gdriveRadioButton" toggleGroup="${predefinedLocationToggler}" text="Google Drive" visible="${controller.observedLocationPresets.foundGdrive}" managed="${controller.observedLocationPresets.foundGdrive}"/>
|
||||||
|
<RadioButton fx:id="onedriveRadioButton" toggleGroup="${predefinedLocationToggler}" text="OneDrive" visible="${controller.observedLocationPresets.foundOnedrive}" managed="${controller.observedLocationPresets.foundOnedrive}"/>
|
||||||
|
<RadioButton fx:id="megaRadioButton" toggleGroup="${predefinedLocationToggler}" text="MEGA" visible="${controller.observedLocationPresets.foundMega}" managed="${controller.observedLocationPresets.foundMega}"/>
|
||||||
|
<RadioButton fx:id="pcloudRadioButton" toggleGroup="${predefinedLocationToggler}" text="pCloud" visible="${controller.observedLocationPresets.foundPcloud}" managed="${controller.observedLocationPresets.foundPcloud}"/>
|
||||||
<HBox spacing="12" alignment="CENTER_LEFT">
|
<HBox spacing="12" alignment="CENTER_LEFT">
|
||||||
<RadioButton fx:id="customRadioButton" toggleGroup="${locationPresetsToggler}" text="%addvaultwizard.new.directoryPickerLabel"/>
|
<RadioButton fx:id="customRadioButton" toggleGroup="${predefinedLocationToggler}" text="%addvaultwizard.new.directoryPickerLabel"/>
|
||||||
<Button contentDisplay="LEFT" text="%addvaultwizard.new.directoryPickerButton" onAction="#chooseCustomVaultPath" disable="${controller.usePresetPath}">
|
<Button contentDisplay="LEFT" text="%addvaultwizard.new.directoryPickerButton" onAction="#chooseCustomVaultPath" disable="${controller.usePresetPath}">
|
||||||
<graphic>
|
<graphic>
|
||||||
<FontAwesome5IconView glyph="FOLDER_OPEN"/>
|
<FontAwesome5IconView glyph="FOLDER_OPEN"/>
|
||||||
@@ -46,8 +51,8 @@
|
|||||||
|
|
||||||
<VBox spacing="6">
|
<VBox spacing="6">
|
||||||
<Label text="%addvaultwizard.new.locationLabel" labelFor="$locationTextField"/>
|
<Label text="%addvaultwizard.new.locationLabel" labelFor="$locationTextField"/>
|
||||||
<TextField fx:id="locationTextField" promptText="%addvaultwizard.new.locationPrompt" text="${controller.vaultPath}" editable="false" disable="${!controller.anyRadioButtonSelected}" HBox.hgrow="ALWAYS"/>
|
<TextField promptText="%addvaultwizard.new.locationPrompt" text="${controller.vaultPath}" editable="false" disable="${!controller.anyRadioButtonSelected}" HBox.hgrow="ALWAYS"/>
|
||||||
<Label fx:id="locationStatusLabel" alignment="CENTER_RIGHT" wrapText="true" visible="${controller.anyRadioButtonSelected}" maxWidth="Infinity" graphicTextGap="6" />
|
<Label fx:id="vaultPathStatus" styleClass="label-muted" alignment="CENTER_RIGHT" wrapText="true" visible="${controller.anyRadioButtonSelected}" maxWidth="Infinity" graphicTextGap="6" text="${controller.statusText}" graphic="${controller.statusGraphic}" />
|
||||||
</VBox>
|
</VBox>
|
||||||
|
|
||||||
<Region VBox.vgrow="ALWAYS"/>
|
<Region VBox.vgrow="ALWAYS"/>
|
||||||
|
|||||||
@@ -1,233 +0,0 @@
|
|||||||
# Locale Specific CSS files such as CJK, RTL,...
|
|
||||||
|
|
||||||
# Generics
|
|
||||||
## Button
|
|
||||||
generic.button.apply=Прилагане
|
|
||||||
generic.button.back=Назад
|
|
||||||
generic.button.cancel=Отказ
|
|
||||||
generic.button.change=Променяне
|
|
||||||
generic.button.choose=Избиране…
|
|
||||||
generic.button.close=Затваряне
|
|
||||||
generic.button.copy=Копиране
|
|
||||||
generic.button.copied=Копирано!
|
|
||||||
generic.button.done=Готово
|
|
||||||
generic.button.next=Напред
|
|
||||||
generic.button.print=Отпечатване
|
|
||||||
|
|
||||||
# Error
|
|
||||||
error.message=Възникна грешка
|
|
||||||
error.description=Това е неочаквано за Криптоматор. Можете да потърсите съществуващи ревения за тази грешка. Или ако все още не е докладвана се чувствайте свободни да го направите.
|
|
||||||
error.hyperlink.lookup=Търсене на грешката
|
|
||||||
error.hyperlink.report=Докладване на грешката
|
|
||||||
error.technicalDetails=Подробности:
|
|
||||||
|
|
||||||
# Defaults
|
|
||||||
defaults.vault.vaultName=Хранилище
|
|
||||||
|
|
||||||
# Tray Menu
|
|
||||||
traymenu.showMainWindow=Показване
|
|
||||||
traymenu.showPreferencesWindow=Настройки
|
|
||||||
traymenu.lockAllVaults=Заключване на всички
|
|
||||||
traymenu.quitApplication=Изход
|
|
||||||
traymenu.vault.unlock=Отключване
|
|
||||||
traymenu.vault.lock=Заключване
|
|
||||||
traymenu.vault.reveal=Разкриване
|
|
||||||
|
|
||||||
# Add Vault Wizard
|
|
||||||
addvaultwizard.title=Добавяне на хранилище
|
|
||||||
## Welcome
|
|
||||||
addvaultwizard.welcome.newButton=Ново хранилище
|
|
||||||
addvaultwizard.welcome.existingButton=Отваряне на хранилище
|
|
||||||
## New
|
|
||||||
### Name
|
|
||||||
addvaultwizard.new.nameInstruction=Изберете име на хранилището
|
|
||||||
addvaultwizard.new.namePrompt=Наименование
|
|
||||||
### Location
|
|
||||||
addvaultwizard.new.locationInstruction=Къде Криптоматор ще държи шифрованите файлове на хранилището?
|
|
||||||
addvaultwizard.new.locationLabel=Местоположение на хранилището
|
|
||||||
addvaultwizard.new.locationPrompt=…
|
|
||||||
addvaultwizard.new.directoryPickerLabel=Потребителско местоположение
|
|
||||||
addvaultwizard.new.directoryPickerButton=Избиране…
|
|
||||||
addvaultwizard.new.directoryPickerTitle=Избор на папка
|
|
||||||
addvaultwizard.new.fileAlreadyExists=Файл или папка с името на хранилището вече съществува
|
|
||||||
addvaultwizard.new.locationDoesNotExist=Папка на посоченото място не съществува или не може да бъде достъпена
|
|
||||||
addvaultwizard.new.locationIsNotWritable=Липсват права за писане на посоченото място
|
|
||||||
addvaultwizard.new.locationIsOk=Мястото е подходящо за хранилище
|
|
||||||
addvaultwizard.new.invalidName=Неприемливо име на хранилище
|
|
||||||
addvaultwizard.new.validName=Приемливо име на хранилище
|
|
||||||
addvaultwizard.new.validCharacters.message=Името на хранилището може да съдържа следните знаци:
|
|
||||||
addvaultwizard.new.validCharacters.chars=Букви (напр. a, ж или 수)
|
|
||||||
addvaultwizard.new.validCharacters.numbers=Числа
|
|
||||||
addvaultwizard.new.validCharacters.dashes=Тире (%s) или долна черта (%s)
|
|
||||||
### Password
|
|
||||||
addvaultwizard.new.createVaultBtn=Създаване
|
|
||||||
addvaultwizard.new.generateRecoveryKeyChoice=Без парола няма да имате достъп до данните си. Желаете ли да бъде създаден ключ за възстановяване, в случай че загубите паролата си?
|
|
||||||
addvaultwizard.new.generateRecoveryKeyChoice.yes=Да, нека имам за всеки случай
|
|
||||||
addvaultwizard.new.generateRecoveryKeyChoice.no=Не, няма да загубя паролата си
|
|
||||||
### Information
|
|
||||||
addvault.new.readme.storageLocation.1=⚠️ ФАЙЛОВЕ НА ХРАНИЛИЩЕ ⚠️
|
|
||||||
addvault.new.readme.storageLocation.2=Това е местоположението на хранилището.
|
|
||||||
addvault.new.readme.storageLocation.3=НЕДЕЙТЕ
|
|
||||||
addvault.new.readme.storageLocation.4=• да променяте файловете в тази папка или
|
|
||||||
addvault.new.readme.storageLocation.5=• да добавяте файлове, които да бъдат шифровани в папката.
|
|
||||||
addvault.new.readme.storageLocation.6=Ако искате някакви файлове да бъдат шифровани или да прегледате хранилището, направете следното:
|
|
||||||
addvault.new.readme.storageLocation.7=1. Добавете това хранилище към Криптоматор.
|
|
||||||
addvault.new.readme.storageLocation.8=2. Отключете хранилището в Криптоматор.
|
|
||||||
addvault.new.readme.storageLocation.9=3. Отворете местоположението на съдържанието чрез бутона „Разкриване“.
|
|
||||||
addvault.new.readme.storageLocation.10=Ако имате нужда от помощ, посетете документацията: %s
|
|
||||||
addvault.new.readme.accessLocation.1=🔐️ ШИФРОВАН ДЯЛ 🔐️
|
|
||||||
addvault.new.readme.accessLocation.2=Това е местоположението на съдържанието на хранилището.
|
|
||||||
addvault.new.readme.accessLocation.3=Файловете, в този дял са шифроване от Криптоматор. Можете да работите с тях както с всеки друг диск или папка. Това е само разшифрован вариант на съдуржанието. Файловете остават шифровани на твърдия диск през цялото време.
|
|
||||||
addvault.new.readme.accessLocation.4=При желание можете да премахнете този файл.
|
|
||||||
## Existing
|
|
||||||
addvaultwizard.existing.instruction=Изберете файла „vault.cryptomator“ от съществуващото хранилище. Но ако съществува файл „masterkey.cryptomator“, изберете него.
|
|
||||||
addvaultwizard.existing.chooseBtn=Избиране…
|
|
||||||
addvaultwizard.existing.filePickerTitle=Избор на файл на хранилището
|
|
||||||
addvaultwizard.existing.filePickerMimeDesc=Хранилище на Криптоматор
|
|
||||||
## Success
|
|
||||||
addvaultwizard.success.nextStepsInstructions=Хранилището „%s“ е добавено.\nЗа да го достъпите или да добавите съдържание в него трябва да го отключите. Можете да го направите сега или по всяко друго време.
|
|
||||||
addvaultwizard.success.unlockNow=Отключване сега
|
|
||||||
|
|
||||||
# Remove Vault
|
|
||||||
removeVault.title=Премахване на „%s“
|
|
||||||
removeVault.message=Премахване на хранилище?
|
|
||||||
removeVault.description=По този начин Криптоматор ще забрави за това хранилище. Можете да го добавите отново. Шифрованите файлове няма да бъдат премахнати от твърдия диск.
|
|
||||||
removeVault.confirmBtn=Премахване
|
|
||||||
|
|
||||||
# Change Password
|
|
||||||
changepassword.title=Промяна на парола
|
|
||||||
changepassword.enterOldPassword=Въведете текущата парола за %s
|
|
||||||
changepassword.finalConfirmation=Разбирам, че ще загубя достъпа до данните си ако забравя паролата
|
|
||||||
|
|
||||||
# Forget Password
|
|
||||||
forgetPassword.title=Забравяне на парола
|
|
||||||
forgetPassword.message=Забравяне на запазена парола?
|
|
||||||
forgetPassword.description=По този начин запазената парола за хранилището ще бъде премахната от ключодържателя на системата.
|
|
||||||
forgetPassword.confirmBtn=Забравяне на парола
|
|
||||||
|
|
||||||
# Unlock
|
|
||||||
unlock.title=Отключване на „%s“
|
|
||||||
unlock.passwordPrompt=Въведете паролата за „%s“:
|
|
||||||
unlock.savePassword=Запомняне на паролата
|
|
||||||
unlock.unlockBtn=Отключване
|
|
||||||
## Select
|
|
||||||
unlock.chooseMasterkey.message=Файлът на главния ключ не е намерен
|
|
||||||
unlock.chooseMasterkey.description=Криптоматор не може да намери файлът на главния ключ на хранилището „%s“. Изберете ръчно файла.
|
|
||||||
unlock.chooseMasterkey.filePickerTitle=Изберете файл на главен ключ
|
|
||||||
unlock.chooseMasterkey.filePickerMimeDesc=Гкавен ключ на Криптоматор
|
|
||||||
## Success
|
|
||||||
unlock.success.message=Отключено е успешно
|
|
||||||
unlock.success.description=Съдържанието на хранилището „%s“ е достъпно в точката му на монтиране.
|
|
||||||
unlock.success.revealBtn=Разкриване на диска
|
|
||||||
## Failure
|
|
||||||
## Hub
|
|
||||||
hub.noKeychain.openBtn=Към настройките
|
|
||||||
### Waiting
|
|
||||||
### Receive Key
|
|
||||||
### Register Device
|
|
||||||
### Registration Success
|
|
||||||
### Registration Failed
|
|
||||||
### Unauthorized
|
|
||||||
### License Exceeded
|
|
||||||
|
|
||||||
# Lock
|
|
||||||
## Force
|
|
||||||
## Failure
|
|
||||||
|
|
||||||
# Migration
|
|
||||||
## Start
|
|
||||||
## Run
|
|
||||||
## Success
|
|
||||||
migration.success.unlockNow=Отключване сега
|
|
||||||
## Missing file system capabilities
|
|
||||||
## Impossible
|
|
||||||
|
|
||||||
# Health Check
|
|
||||||
## Start
|
|
||||||
health.title=Проверка на състоянието на „%s“
|
|
||||||
health.intro.header=Проверка на състоянието
|
|
||||||
health.intro.text=Проверката на състоянието е набор от проверки и евентуално поправки за проблеми във вътрешната структура на хранилището. Имайте предвид, че:
|
|
||||||
## Start Failure
|
|
||||||
## Check Selection
|
|
||||||
## Detail view
|
|
||||||
health.check.detail.listFilters.label=Филтър
|
|
||||||
health.check.detail.fixAllSpecificBtn=Поправка всички от вида
|
|
||||||
health.check.exportBtn=Отчет
|
|
||||||
## Result view
|
|
||||||
health.result.severityFilter.all=Сериозност - Всички
|
|
||||||
health.result.severityFilter.good=Добре
|
|
||||||
health.result.severityFilter.info=Информация
|
|
||||||
health.result.severityFilter.warn=Предупреждение
|
|
||||||
health.result.severityFilter.crit=Криточно
|
|
||||||
## Fix Application
|
|
||||||
|
|
||||||
# Preferences
|
|
||||||
preferences.title=Настройки
|
|
||||||
## General
|
|
||||||
## Interface
|
|
||||||
preferences.interface.theme=Оформление
|
|
||||||
## Volume
|
|
||||||
## Updates
|
|
||||||
## Contribution
|
|
||||||
#<-- Add entries for donations and code/translation/documentation contribution -->
|
|
||||||
|
|
||||||
## About
|
|
||||||
|
|
||||||
# Vault Statistics
|
|
||||||
## Read
|
|
||||||
## Write
|
|
||||||
|
|
||||||
## Accesses
|
|
||||||
|
|
||||||
|
|
||||||
# Main Window
|
|
||||||
main.closeBtn.tooltip=Затваряне
|
|
||||||
main.preferencesBtn.tooltip=Настройки
|
|
||||||
## Vault List
|
|
||||||
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
|
|
||||||
### Locked
|
|
||||||
main.vaultDetail.unlockBtn=Отключване…
|
|
||||||
main.vaultDetail.unlockNowBtn=Отключване сега
|
|
||||||
### Unlocked
|
|
||||||
main.vaultDetail.unlockedStatus=ОТКЛЮЧЕНО
|
|
||||||
main.vaultDetail.revealBtn=Разкриване на диска
|
|
||||||
main.vaultDetail.lockBtn=Заключване
|
|
||||||
### Missing
|
|
||||||
### Needs Migration
|
|
||||||
### Error
|
|
||||||
|
|
||||||
# Wrong File Alert
|
|
||||||
|
|
||||||
# Vault Options
|
|
||||||
## General
|
|
||||||
vaultOptions.general.vaultName=Наименование
|
|
||||||
vaultOptions.general.actionAfterUnlock.reveal=Разкриване на диска
|
|
||||||
vaultOptions.general.actionAfterUnlock.ask=Запитване
|
|
||||||
|
|
||||||
## Mount
|
|
||||||
vaultOptions.mount.mountPoint.directoryPickerButton=Избиране…
|
|
||||||
## Master Key
|
|
||||||
vaultOptions.masterkey.changePasswordBtn=Промяна на парола
|
|
||||||
## Hub
|
|
||||||
|
|
||||||
# Recovery Key
|
|
||||||
## Display Recovery Key
|
|
||||||
## Reset Password
|
|
||||||
### Enter Recovery Key
|
|
||||||
### Reset Password
|
|
||||||
### Recovery Key Password Reset Success
|
|
||||||
|
|
||||||
# Convert Vault
|
|
||||||
|
|
||||||
# New Password
|
|
||||||
|
|
||||||
# Quit
|
|
||||||
|
|
||||||
# Forced Quit
|
|
||||||
@@ -172,8 +172,8 @@ migration.title=Tresor upgraden
|
|||||||
## Start
|
## Start
|
||||||
migration.start.header=Tresor upgraden
|
migration.start.header=Tresor upgraden
|
||||||
migration.start.text=Um deinen Tresor "%s" in dieser neuen Version von Cryptomator zu öffnen, muss der Tresor auf ein neueres Format aktualisiert werden. Bevor du dies tust, solltest du Folgendes wissen:
|
migration.start.text=Um deinen Tresor "%s" in dieser neuen Version von Cryptomator zu öffnen, muss der Tresor auf ein neueres Format aktualisiert werden. Bevor du dies tust, solltest du Folgendes wissen:
|
||||||
migration.start.remarkUndone=Diese Aktualisierung kann nicht rückgängig gemacht werden.
|
migration.start.remarkUndone=Dieser Vorgang kann nicht rückgängig gemacht werden.
|
||||||
migration.start.remarkVersions=Ältere Versionen von Cryptomator werden den aktualisierten Tresor nicht öffnen können.
|
migration.start.remarkVersions=Ältere Versionen von Cryptomator können den aktualisierten Tresor nicht öffnen.
|
||||||
migration.start.remarkCanRun=Du musst sicherstellen, dass jedes Gerät, von dem aus du auf den Tresor zugreifst, diese Version von Cryptomator ausführen kann.
|
migration.start.remarkCanRun=Du musst sicherstellen, dass jedes Gerät, von dem aus du auf den Tresor zugreifst, diese Version von Cryptomator ausführen kann.
|
||||||
migration.start.remarkSynced=Du musst sicherstellen, dass dein Tresor auf diesem Gerät und auf deinen anderen Geräten vollständig synchronisiert ist, bevor du ihn aktualisierst.
|
migration.start.remarkSynced=Du musst sicherstellen, dass dein Tresor auf diesem Gerät und auf deinen anderen Geräten vollständig synchronisiert ist, bevor du ihn aktualisierst.
|
||||||
migration.start.confirm=Ich habe die oben genannten Informationen gelesen und verstanden
|
migration.start.confirm=Ich habe die oben genannten Informationen gelesen und verstanden
|
||||||
@@ -225,7 +225,7 @@ health.check.detail.checkFinishedAndFound=Die Prüfung wurde abgeschlossen. Bitt
|
|||||||
health.check.detail.checkFailed=Die Prüfung wurde wegen eines Fehlers abgebrochen.
|
health.check.detail.checkFailed=Die Prüfung wurde wegen eines Fehlers abgebrochen.
|
||||||
health.check.detail.checkCancelled=Die Prüfung wurde abgebrochen.
|
health.check.detail.checkCancelled=Die Prüfung wurde abgebrochen.
|
||||||
health.check.detail.listFilters.label=Filter
|
health.check.detail.listFilters.label=Filter
|
||||||
health.check.detail.fixAllSpecificBtn=Behebe alle vom Typ
|
health.check.detail.fixAllSpecificBtn=Alle dieses Typs reparieren
|
||||||
health.check.exportBtn=Bericht exportieren
|
health.check.exportBtn=Bericht exportieren
|
||||||
## Result view
|
## Result view
|
||||||
health.result.severityFilter.all=Schweregrad - Alle
|
health.result.severityFilter.all=Schweregrad - Alle
|
||||||
@@ -464,7 +464,7 @@ convertVault.title=Tresor konvertieren
|
|||||||
convertVault.convert.convertBtn.before=Konvertieren
|
convertVault.convert.convertBtn.before=Konvertieren
|
||||||
convertVault.convert.convertBtn.processing=Konvertierung läuft…
|
convertVault.convert.convertBtn.processing=Konvertierung läuft…
|
||||||
convertVault.success.message=Konvertierung erfolgreich
|
convertVault.success.message=Konvertierung erfolgreich
|
||||||
convertVault.hubToPassword.success.description=Du kannst nun den Tresor mit dem gewählten Passwort entsperren, ohne Hub Zugriff zu benötigen.
|
convertVault.hubToPassword.success.description=Du kannst nun den Tresor mit dem gewählten Passwort entsperren, ohne auf den Hub zuzugreifen.
|
||||||
|
|
||||||
# New Password
|
# New Password
|
||||||
newPassword.promptText=Gib ein neues Passwort ein
|
newPassword.promptText=Gib ein neues Passwort ein
|
||||||
|
|||||||
@@ -1,258 +0,0 @@
|
|||||||
# Locale Specific CSS files such as CJK, RTL,...
|
|
||||||
|
|
||||||
# Generics
|
|
||||||
## Button
|
|
||||||
generic.button.apply=Vahvista
|
|
||||||
generic.button.back=Takaisin
|
|
||||||
generic.button.cancel=Peruuta
|
|
||||||
generic.button.change=Muuta
|
|
||||||
generic.button.choose=Valitse…
|
|
||||||
generic.button.close=Sulje
|
|
||||||
generic.button.copy=Kopioi
|
|
||||||
generic.button.copied=Kopioitu!
|
|
||||||
generic.button.done=Valmis
|
|
||||||
generic.button.next=Seuraava
|
|
||||||
generic.button.print=Tulosta
|
|
||||||
|
|
||||||
# Error
|
|
||||||
error.message=Tapahtui virhe
|
|
||||||
error.description=Cryptomator ei odottanut tämän tapahtuvan. Voit etsiä olemassa olevia ratkaisuja tähän virheeseen. Tai jos sitä ei ole vielä raportoitu, voit tehdä niin.
|
|
||||||
error.hyperlink.lookup=Etsi tämä virhe
|
|
||||||
error.hyperlink.report=Ilmoita ongelmasta
|
|
||||||
error.technicalDetails=Tiedot:
|
|
||||||
|
|
||||||
# Defaults
|
|
||||||
defaults.vault.vaultName=Vault
|
|
||||||
|
|
||||||
# Tray Menu
|
|
||||||
traymenu.showMainWindow=Näytä
|
|
||||||
traymenu.showPreferencesWindow=Asetukset
|
|
||||||
traymenu.lockAllVaults=Lukitse Kaikki
|
|
||||||
traymenu.quitApplication=Sulje
|
|
||||||
traymenu.vault.unlock=Avaa
|
|
||||||
traymenu.vault.lock=Lukitse
|
|
||||||
traymenu.vault.reveal=Paljasta
|
|
||||||
|
|
||||||
# Add Vault Wizard
|
|
||||||
addvaultwizard.title=Lisää Vault
|
|
||||||
## Welcome
|
|
||||||
addvaultwizard.welcome.newButton=Luo Uusi Vault
|
|
||||||
addvaultwizard.welcome.existingButton=Avaa Olemassaoleva Vault
|
|
||||||
## New
|
|
||||||
### Name
|
|
||||||
addvaultwizard.new.nameInstruction=Anna uusi nimi Vaultille
|
|
||||||
addvaultwizard.new.namePrompt=Vault Nimi
|
|
||||||
### Location
|
|
||||||
addvaultwizard.new.locationInstruction=Missä pitäisi Cryptomator tallentaa salattuja tiedostoja Vault?
|
|
||||||
addvaultwizard.new.locationLabel=Tallennustilan sijainti
|
|
||||||
addvaultwizard.new.locationPrompt=…
|
|
||||||
addvaultwizard.new.directoryPickerLabel=Oma sijainti
|
|
||||||
addvaultwizard.new.directoryPickerButton=Valitse…
|
|
||||||
addvaultwizard.new.directoryPickerTitle=Valitse Hakemisto
|
|
||||||
addvaultwizard.new.fileAlreadyExists=Varoitus: samanniminen tiedosto tai Vault on jo olemassa!
|
|
||||||
addvaultwizard.new.locationDoesNotExist=Määritetyn polun hakemistoa ei ole olemassa tai sitä ei voi käyttää
|
|
||||||
addvaultwizard.new.locationIsNotWritable=Ei kirjoitusoikeuksia määritetyllä polulla
|
|
||||||
addvaultwizard.new.locationIsOk=Sopiva sijainti Vaultille
|
|
||||||
addvaultwizard.new.invalidName=Virheellinen vault nimi
|
|
||||||
addvaultwizard.new.validName=Kelvollinen vault nimi
|
|
||||||
addvaultwizard.new.validCharacters.message=Vaultin nimi voi sisältää seuraavat merkit:
|
|
||||||
addvaultwizard.new.validCharacters.chars=Sanamerkit (e.g. a, ж or 수)
|
|
||||||
addvaultwizard.new.validCharacters.numbers=Numerot
|
|
||||||
addvaultwizard.new.validCharacters.dashes=Hyphen (%s) tai alaviiva (%s)
|
|
||||||
### Password
|
|
||||||
addvaultwizard.new.createVaultBtn=Luo Uusi Vault
|
|
||||||
addvaultwizard.new.generateRecoveryKeyChoice=Et voi käyttää tietojasi ilman salasanaasi. Haluatko palautusavaimen siltä varalta, että menetät salasanasi?
|
|
||||||
addvaultwizard.new.generateRecoveryKeyChoice.yes=Kyllä kiitos, parempi olla varma kuin katua
|
|
||||||
addvaultwizard.new.generateRecoveryKeyChoice.no=Ei kiitos, en menetä salasanani
|
|
||||||
### Information
|
|
||||||
addvault.new.readme.storageLocation.fileName=IMPORTANT.rtf
|
|
||||||
addvault.new.readme.storageLocation.1=⚠️ VAULT TIEDOSTOT⚠️
|
|
||||||
addvault.new.readme.storageLocation.2=Tämä on vaultin tallennuspaikka.
|
|
||||||
addvault.new.readme.storageLocation.3=ÄLÄ
|
|
||||||
addvault.new.readme.storageLocation.4=• muuttaa mitä tahansa tiedostoja tämän hakemiston tai
|
|
||||||
addvault.new.readme.storageLocation.5=• liitä kaikki tiedostot salaukseen tähän kansioon.
|
|
||||||
addvault.new.readme.storageLocation.6=Jos haluat salata tiedostoja ja tarkastella Vaultin sisältöä, tee seuraavat toimet:
|
|
||||||
addvault.new.readme.storageLocation.7=1. Lisää tämä Vault Cryptomatoriin.
|
|
||||||
addvault.new.readme.storageLocation.8=2. Avaa Vault Cryptomatorissa.
|
|
||||||
addvault.new.readme.storageLocation.9=3. Avaa tallennuskansiosi klikkaamalla "Näytä" -painiketta.
|
|
||||||
addvault.new.readme.storageLocation.10=Mikäli tarvitset apua, konsultoi Cryptomatorin dokumentaatiota: %s
|
|
||||||
addvault.new.readme.accessLocation.fileName=TERVETULOA.rtf
|
|
||||||
addvault.new.readme.accessLocation.1=🔐️ SALATTU VOLYYMI 🔐️
|
|
||||||
addvault.new.readme.accessLocation.2=Tämä on salatun holvisi tallennuskansio.
|
|
||||||
addvault.new.readme.accessLocation.3=Cryptomator salaa kaikki tänne siirtämäsi tiedostot. Voit työskennellä tässä kansiossa aivan samalla tavalla kuin muutenkin. Tämä on ainoastaan näkymä jossa salaus on purettu. Todellisuudessa kaikki tiedostot pysyvät salattuina aina.
|
|
||||||
addvault.new.readme.accessLocation.4=Voit halutessasi poistaa tämän tiedoston. Poistaminen ei vaikuta Cryptomatorin toimintaan.
|
|
||||||
## Existing
|
|
||||||
addvaultwizard.existing.instruction=Valitse olemassa olevan Cryptomator holvin "vault.cryptomator" -tiedosto. Mikäli "vault.cryptomator" -tiedostoa ei ole, valitse "masterkey.cryptomator" -tiedosto.
|
|
||||||
addvaultwizard.existing.chooseBtn=Valitse…
|
|
||||||
addvaultwizard.existing.filePickerTitle=Valitse Holvi -tiedosto
|
|
||||||
addvaultwizard.existing.filePickerMimeDesc=Cryptomator Holvi
|
|
||||||
## Success
|
|
||||||
addvaultwizard.success.nextStepsInstructions=Holvi "%s" on lisätty.\nSinun täytyy avata kyseinen holvi tarkastellaksesi sen sisältöä. Vaihtoehtoisesti voit avata sen myöhemmin koska tahansa.
|
|
||||||
addvaultwizard.success.unlockNow=Avaa Nyt
|
|
||||||
|
|
||||||
# Remove Vault
|
|
||||||
removeVault.title=Poista "%s"
|
|
||||||
removeVault.message=Poistetaanko holvi?
|
|
||||||
removeVault.description=Tämä toiminto ainoastaan poistaa valitun holvin Cryptomatorin näkymästä. Salattuja tiedostoja tai holvia itsessään ei poisteta.
|
|
||||||
removeVault.confirmBtn=Poista Holvi
|
|
||||||
|
|
||||||
# Change Password
|
|
||||||
changepassword.title=Vaihda salasana
|
|
||||||
changepassword.enterOldPassword=Syötä "%s": n nykyinen salasana
|
|
||||||
changepassword.finalConfirmation=Ymmärrän, että tiedostojani ei voi palauttaa, mikäli unohdan salasanani.
|
|
||||||
|
|
||||||
# Forget Password
|
|
||||||
forgetPassword.title=Unohda Salasana
|
|
||||||
forgetPassword.message=Unohda tallennetut salasanat?
|
|
||||||
forgetPassword.description=Tämä poistaa valitun holvin tallennetun salasanan järjestelmäsi avainrenkaasta.
|
|
||||||
forgetPassword.confirmBtn=Unohda Salasana
|
|
||||||
|
|
||||||
# Unlock
|
|
||||||
unlock.title=Avaa "%s"
|
|
||||||
unlock.passwordPrompt=Syötä salasana "%s":lle
|
|
||||||
unlock.savePassword=Muista salasana
|
|
||||||
unlock.unlockBtn=Avaa
|
|
||||||
## Select
|
|
||||||
unlock.chooseMasterkey.message=Masterkey -tiedostoa ei löydy
|
|
||||||
unlock.chooseMasterkey.description=Cryptomator ei paikantanut masterkey -tiedostoa holville "%s". Ole hyvä ja valitse tiedosto manuaalisesti.
|
|
||||||
unlock.chooseMasterkey.filePickerTitle=Valitse Masterkey -tiedosto
|
|
||||||
unlock.chooseMasterkey.filePickerMimeDesc=Cryptomator Masterkey
|
|
||||||
## Success
|
|
||||||
unlock.success.message=Lukituksen purku onnistui
|
|
||||||
unlock.success.description="%s" holvin sisältö on nyt saatavilla sen hallinnointikohteessa.
|
|
||||||
unlock.success.rememberChoice=Muista valintani. Älä kysy uudelleen.
|
|
||||||
unlock.success.revealBtn=Paljasta Asema
|
|
||||||
## Failure
|
|
||||||
unlock.error.customPath.message=Holvia ei pystytty yhdistämään valittuun polkuun
|
|
||||||
unlock.error.customPath.description.notSupported=Mikäli haluat jatkaa mukautetun polun käyttöä, ole hyvä ja mene Asetuksiin ja valitse volyymityyppi mikä tukee sitä. Muussa tapauksessa avaa holvin asetukset ja valitse tuettu mukautettu polku.
|
|
||||||
unlock.error.customPath.description.notExists=Valitsemaasi mukautettua polkua ei ole olemassa. Voit joko luoda uuden polun tai muuttaa polkua holvisi asetuksissa.
|
|
||||||
unlock.error.customPath.description.generic=Olet valinnut mukautetun polun holvillesi, mutta sen kanssa ilmeni ongelma: %s
|
|
||||||
## Hub
|
|
||||||
hub.noKeychain.message=Laitteen avainta ei löytynyt
|
|
||||||
hub.noKeychain.description=Hub-holvien purkamiseksi tarvitaan laiteavain joka on suojattu avainrenkaalla. Jatkaaksesi, kytke “%s” päälle ja valitse avainrengas asetuksista.
|
|
||||||
hub.noKeychain.openBtn=Avaa asetukset
|
|
||||||
### Waiting
|
|
||||||
hub.auth.message=Odotetaan todennusta…
|
|
||||||
hub.auth.description=Pitäisi ohjata sinut automaattisesti uudelleen kirjautumissivulle.
|
|
||||||
hub.auth.loginLink=Uudelleenohjaus epäonnistui? Avaa tästä manuaalisesti.
|
|
||||||
### Receive Key
|
|
||||||
hub.receive.message=Odotetaan vastausta…
|
|
||||||
hub.receive.description=Cryptomator yhdistää Hub:iin. Ole hyvä ja odota.
|
|
||||||
### Register Device
|
|
||||||
hub.register.message=Laitteen nimi vaaditaan
|
|
||||||
hub.register.description=Et ole ilmeisesti ennen yhdistänyt Hub:iin tältä laitteelta. Jotta pääsyoikeus voidaan todentaa, sinun täytyy nimetä tämä laite.
|
|
||||||
hub.register.nameLabel=Laitteen Nimi
|
|
||||||
hub.register.occupiedMsg=Tämä nimi on jo käytössä
|
|
||||||
hub.register.registerBtn=Vahvista
|
|
||||||
### Registration Success
|
|
||||||
hub.registerSuccess.message=Laite nimetty onnistuneesti
|
|
||||||
hub.registerSuccess.description=Käyttääksesi holvia, holvin omistajan on valtuutettava laitteesi.
|
|
||||||
### Registration Failed
|
|
||||||
hub.registerFailed.message=Laitteen nimeäminen epäonnistui
|
|
||||||
hub.registerFailed.description=Nimeämisprosessissa tapahtui virhe. Löydät lisää tietoja lokitiedostoista.
|
|
||||||
### Unauthorized
|
|
||||||
hub.unauthorized.message=Pääsy estetty
|
|
||||||
hub.unauthorized.description=Laitteellasi ei ole pääsyvaltuutusta tähän holviin. Pyydä holvin omistajaa lisäämän valtuutus laitteellesi.
|
|
||||||
### License Exceeded
|
|
||||||
hub.invalidLicense.message=Hub-lisenssi ei ole voimassa
|
|
||||||
hub.invalidLicense.description=Cryptomator Hub:illasi ei ole voimassa olevaa lisenssiä. Ole hyvä ja ilmoita Hubin järjestelmänvalvojalle lisenssin päivittämiseksi tai sen uusimiseksi.
|
|
||||||
|
|
||||||
# Lock
|
|
||||||
## Force
|
|
||||||
lock.forced.message=Lukitus epäonnistui
|
|
||||||
lock.forced.description="%s":n lukitus epäonnistui, koska sinulla on avoimia tiedostoja tai niihin liittyviä päivityksiä vireillä. Voit halutessasi pakottaa lukituksen, mutta tämä saattaa johtaa tallentamattomien tiedostojen katoamiseen.
|
|
||||||
lock.forced.retryBtn=Yritä uudestaan
|
|
||||||
lock.forced.forceBtn=Pakota Lukitus
|
|
||||||
## Failure
|
|
||||||
lock.fail.message=Holvin lukitseminen epäonnistui
|
|
||||||
lock.fail.description="%s" holvia ei voitu lukita. Varmista, että avoinna olevat tiedostot tallennetaan turvalliseen paikkaan ja että tiedostot eivät ole avoinna tai käytössä. Lukitaksesi holvin, pakota Cryptomator -prosessin lopetus manuaalisesti.
|
|
||||||
|
|
||||||
# Migration
|
|
||||||
migration.title=Päivitä Holvi
|
|
||||||
## Start
|
|
||||||
migration.start.header=Päivitä Holvi
|
|
||||||
migration.start.text="%s" holvi tulee päivittää uuteen versioon, jotta voit avata sen Cryptomatorissa. Ennen kuin jatkat, varmista että ymmärrät seuraavan:
|
|
||||||
migration.start.remarkUndone=Päivitystä ei voi peruuttaa.
|
|
||||||
migration.start.remarkVersions=Cryptomatorin vanhemmat versiot eivät voi avata päivitettyä holvia.
|
|
||||||
migration.start.remarkCanRun=Sinun tulee varmistaa, että kaikki laitteet joilla haluat käyttää tätä holvia on päivitetty Cryptomatorin uusimpaan versioon.
|
|
||||||
migration.start.remarkSynced=Sinun tulee varmistaa, että holvisi on täysin ajantasalla tällä laitteella ja muilla laitteillasi, ennen kuin aloitat päivitysprosessin.
|
|
||||||
migration.start.confirm=Olen lukenut ja ymmärtänyt yllä ilmoitetut ohjeet
|
|
||||||
## Run
|
|
||||||
## Success
|
|
||||||
migration.success.unlockNow=Avaa Nyt
|
|
||||||
## Missing file system capabilities
|
|
||||||
## Impossible
|
|
||||||
|
|
||||||
# Health Check
|
|
||||||
## Start
|
|
||||||
## Start Failure
|
|
||||||
## Check Selection
|
|
||||||
## Detail view
|
|
||||||
## Result view
|
|
||||||
## Fix Application
|
|
||||||
|
|
||||||
# Preferences
|
|
||||||
preferences.title=Asetukset
|
|
||||||
## General
|
|
||||||
## Interface
|
|
||||||
## Volume
|
|
||||||
## Updates
|
|
||||||
## Contribution
|
|
||||||
#<-- Add entries for donations and code/translation/documentation contribution -->
|
|
||||||
|
|
||||||
## About
|
|
||||||
|
|
||||||
# Vault Statistics
|
|
||||||
## Read
|
|
||||||
## Write
|
|
||||||
|
|
||||||
## Accesses
|
|
||||||
|
|
||||||
|
|
||||||
# Main Window
|
|
||||||
main.closeBtn.tooltip=Sulje
|
|
||||||
main.preferencesBtn.tooltip=Asetukset
|
|
||||||
## Vault List
|
|
||||||
main.vaultlist.contextMenu.lock=Lukitse
|
|
||||||
main.vaultlist.contextMenu.unlockNow=Avaa Nyt
|
|
||||||
main.vaultlist.contextMenu.reveal=Paljasta Asema
|
|
||||||
main.vaultlist.addVaultBtn=Lisää Vault
|
|
||||||
## Vault Detail
|
|
||||||
### Welcome
|
|
||||||
### Locked
|
|
||||||
main.vaultDetail.unlockNowBtn=Avaa Nyt
|
|
||||||
### Unlocked
|
|
||||||
main.vaultDetail.revealBtn=Paljasta Asema
|
|
||||||
main.vaultDetail.lockBtn=Lukitse
|
|
||||||
### Missing
|
|
||||||
### Needs Migration
|
|
||||||
main.vaultDetail.migrateButton=Päivitä Holvi
|
|
||||||
### Error
|
|
||||||
|
|
||||||
# Wrong File Alert
|
|
||||||
|
|
||||||
# Vault Options
|
|
||||||
## General
|
|
||||||
vaultOptions.general.vaultName=Vault Nimi
|
|
||||||
vaultOptions.general.actionAfterUnlock.reveal=Paljasta Asema
|
|
||||||
|
|
||||||
## Mount
|
|
||||||
vaultOptions.mount.mountPoint.directoryPickerButton=Valitse…
|
|
||||||
## Master Key
|
|
||||||
vaultOptions.masterkey.changePasswordBtn=Vaihda salasana
|
|
||||||
## Hub
|
|
||||||
|
|
||||||
# Recovery Key
|
|
||||||
## Display Recovery Key
|
|
||||||
## Reset Password
|
|
||||||
### Enter Recovery Key
|
|
||||||
### Reset Password
|
|
||||||
### Recovery Key Password Reset Success
|
|
||||||
|
|
||||||
# Convert Vault
|
|
||||||
|
|
||||||
# New Password
|
|
||||||
|
|
||||||
# Quit
|
|
||||||
|
|
||||||
# Forced Quit
|
|
||||||
@@ -50,41 +50,26 @@ addvaultwizard.new.directoryPickerLabel=Custom Location
|
|||||||
addvaultwizard.new.directoryPickerButton=Mamili…
|
addvaultwizard.new.directoryPickerButton=Mamili…
|
||||||
addvaultwizard.new.directoryPickerTitle=Pumili ng Direktoryo
|
addvaultwizard.new.directoryPickerTitle=Pumili ng Direktoryo
|
||||||
### Password
|
### Password
|
||||||
addvaultwizard.new.createVaultBtn=Gumawa ng bagong Vault
|
|
||||||
### Information
|
### Information
|
||||||
addvault.new.readme.storageLocation.2=Ito ang lokasyon ng iyong vault na imbakan.
|
|
||||||
addvault.new.readme.storageLocation.3=HUWAG
|
|
||||||
addvault.new.readme.storageLocation.6=Kung gusto mo i-encrypt ang mga files at makita nang nilalaman ng vault, gawin ang nakasabi:
|
|
||||||
addvault.new.readme.storageLocation.7=1. Idagdag ang vault na ito sa Cryptomator.
|
|
||||||
addvault.new.readme.accessLocation.2=Ito ang lokasyon ng iyong vault.
|
|
||||||
## Existing
|
## Existing
|
||||||
addvaultwizard.existing.chooseBtn=Mamili…
|
addvaultwizard.existing.chooseBtn=Mamili…
|
||||||
## Success
|
## Success
|
||||||
|
|
||||||
# Remove Vault
|
# Remove Vault
|
||||||
removeVault.title=Tanggalin %s
|
|
||||||
removeVault.message=Itangal ang vault?
|
|
||||||
removeVault.confirmBtn=Itangal ang vault
|
|
||||||
|
|
||||||
# Change Password
|
# Change Password
|
||||||
|
|
||||||
# Forget Password
|
# Forget Password
|
||||||
|
|
||||||
# Unlock
|
# Unlock
|
||||||
unlock.savePassword=Maalala ang password
|
|
||||||
unlock.unlockBtn=I-unlock
|
unlock.unlockBtn=I-unlock
|
||||||
## Select
|
## Select
|
||||||
unlock.chooseMasterkey.filePickerTitle=Piliin ang masterkey file
|
|
||||||
unlock.chooseMasterkey.filePickerMimeDesc=Cryptomator Masterkey
|
|
||||||
## Success
|
## Success
|
||||||
unlock.success.rememberChoice=Paalala ang pinili ko, huwag mag tanong ulit
|
|
||||||
## Failure
|
## Failure
|
||||||
## Hub
|
## Hub
|
||||||
### Waiting
|
### Waiting
|
||||||
### Receive Key
|
### Receive Key
|
||||||
### Register Device
|
### Register Device
|
||||||
hub.register.occupiedMsg=Ang pangalan ay nagamit na
|
|
||||||
hub.register.registerBtn=Kumpirmahin
|
|
||||||
### Registration Success
|
### Registration Success
|
||||||
### Registration Failed
|
### Registration Failed
|
||||||
### Unauthorized
|
### Unauthorized
|
||||||
|
|||||||
@@ -56,9 +56,6 @@ addvaultwizard.new.locationIsOk=Megfelelő hely a trezornak
|
|||||||
addvaultwizard.new.invalidName=Érvénytelen vault név
|
addvaultwizard.new.invalidName=Érvénytelen vault név
|
||||||
addvaultwizard.new.validName=Érvényes vault név
|
addvaultwizard.new.validName=Érvényes vault név
|
||||||
addvaultwizard.new.validCharacters.message=A vault neve a következő karaktereket tartalmazhatja:
|
addvaultwizard.new.validCharacters.message=A vault neve a következő karaktereket tartalmazhatja:
|
||||||
addvaultwizard.new.validCharacters.chars=Szókarakterek (pl. a, ж vagy 수)
|
|
||||||
addvaultwizard.new.validCharacters.numbers=Számok
|
|
||||||
addvaultwizard.new.validCharacters.dashes=Kötőjel (%s) vagy alulvonás (%s)
|
|
||||||
### Password
|
### Password
|
||||||
addvaultwizard.new.createVaultBtn=Új 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=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?
|
||||||
@@ -113,49 +110,28 @@ unlock.passwordPrompt=Írja be a jelszavát a következő széfhez "%s":
|
|||||||
unlock.savePassword=Jelszó megjegyzése
|
unlock.savePassword=Jelszó megjegyzése
|
||||||
unlock.unlockBtn=Feloldás
|
unlock.unlockBtn=Feloldás
|
||||||
## Select
|
## Select
|
||||||
unlock.chooseMasterkey.message=Mesterkulcs fájl nem található
|
|
||||||
unlock.chooseMasterkey.description=Nem található a tároló kulcsfájlja a várt helyen. Kérjük válassza ki a kulcsfájlt manuálisan.
|
unlock.chooseMasterkey.description=Nem található a tároló kulcsfájlja a várt helyen. Kérjük válassza ki a kulcsfájlt manuálisan.
|
||||||
unlock.chooseMasterkey.filePickerTitle=Mesterkulcs fájl kiválasztása
|
unlock.chooseMasterkey.filePickerTitle=Mesterkulcs fájl kiválasztása
|
||||||
unlock.chooseMasterkey.filePickerMimeDesc=Cryptomator Mesterkulcs
|
|
||||||
## Success
|
## Success
|
||||||
unlock.success.message=Sikeres feloldás
|
unlock.success.message=Sikeres feloldás
|
||||||
unlock.success.description="%s" sikreresen feloldásra került! Mostmár hozzáférhet a virtuális trezorhoz.
|
unlock.success.description="%s" sikreresen feloldásra került! Mostmár hozzáférhet a virtuális trezorhoz.
|
||||||
unlock.success.rememberChoice=Jegyezze meg a választást és ne mutassa többet
|
unlock.success.rememberChoice=Jegyezze meg a választást és ne mutassa többet
|
||||||
unlock.success.revealBtn=Széf megjelenítése
|
unlock.success.revealBtn=Széf megjelenítése
|
||||||
## Failure
|
## Failure
|
||||||
unlock.error.customPath.message=Nem lehet csatolni a széfet az egyéni útvonalhoz
|
|
||||||
unlock.error.customPath.description.notSupported=Ha szeretné továbbra is az egyéni útvonalat használni, kérem, menjen a beállításokba és válasszon egy kötet típust, amely támogatja azt. Máskülönben, menjen a széf opciókhoz és válasszon egy támogatott csatoláspontot.
|
|
||||||
unlock.error.customPath.description.notExists=Az egyéni csatolás útvonal nem létezik. Hozza létre a helyi fájlrendszerében vagy változtassa meg a széf opciókban.
|
|
||||||
unlock.error.customPath.description.generic=Egyéni csatolási útvonalat választott ehhez a széfhez, de használatakor ez a hibaüzenet érkezett: %s
|
|
||||||
## Hub
|
## Hub
|
||||||
hub.noKeychain.message=Nem lehet az eszközkulcshoz hozzáférni
|
|
||||||
hub.noKeychain.description=Hogy feloldja a Hub széfeket, egy eszközkulcs szükséges, mely egy kulcslánccal van biztosítva. A folytatáshoz engedélyezze a következőt: “%s” és válasszon egy kulcsláncot a beállításokban.
|
|
||||||
hub.noKeychain.openBtn=Beállítások megnyitása
|
hub.noKeychain.openBtn=Beállítások megnyitása
|
||||||
### Waiting
|
### Waiting
|
||||||
hub.auth.message=Várakozás a hitelesítésre…
|
|
||||||
hub.auth.description=Automatikusan átirányítjuk a bejelentkezési oldalra.
|
|
||||||
hub.auth.loginLink=Nem sikerült az átirányítás? Kattintson ide a megnyitáshoz.
|
|
||||||
### Receive Key
|
### Receive Key
|
||||||
hub.receive.message=Válasz feldolgozása…
|
hub.receive.message=Válasz feldolgozása…
|
||||||
hub.receive.description=Cryptomator fogadja és feldolgozza a Hub válaszát. Kérem, várjon.
|
|
||||||
### Register Device
|
### Register Device
|
||||||
hub.register.message=Eszköznév szükséges
|
|
||||||
hub.register.description=Úgy tűnik, ez az első Hub-hozzáférés erről az eszközről. A hozzáférési jogosultság azonosításához el kell neveznie ezt az eszközt.
|
|
||||||
hub.register.nameLabel=Készülék neve
|
hub.register.nameLabel=Készülék neve
|
||||||
hub.register.occupiedMsg=Ez a név már használatban van
|
hub.register.occupiedMsg=Ez a név már használatban van
|
||||||
hub.register.registerBtn=Megerősítés
|
hub.register.registerBtn=Megerősítés
|
||||||
### Registration Success
|
### Registration Success
|
||||||
hub.registerSuccess.message=Eszköz elnevezve
|
|
||||||
hub.registerSuccess.description=A széf hozzáféréséhez a széf tulajdonosának hitelesítenie kell az eszközét.
|
|
||||||
### Registration Failed
|
### Registration Failed
|
||||||
hub.registerFailed.message=Az eszköz elnevezése sikertelen volt
|
hub.registerFailed.message=Az eszköz elnevezése sikertelen volt
|
||||||
hub.registerFailed.description=Hiba állt fel az elnevezési folyamatban. További részletekért tekintse meg az alkalmazásnaplót.
|
|
||||||
### Unauthorized
|
### Unauthorized
|
||||||
hub.unauthorized.message=Hozzáférés megtagadva
|
|
||||||
hub.unauthorized.description=Eszköze még nem kapott engedélyt ehhez a széfhez. Kérje a széf tulajdonosát, hogy engedélyezze a hozzáférést.
|
|
||||||
### License Exceeded
|
### License Exceeded
|
||||||
hub.invalidLicense.message=Érvénytelen Hub licenc
|
|
||||||
hub.invalidLicense.description=Az Ön Cryptomator Hub példánya érvénytelen licenccel rendelkezik. Kérem, értesítsen egy Hub rendszergazdát hogy frissítse vagy újítsa meg a licencet.
|
|
||||||
|
|
||||||
# Lock
|
# Lock
|
||||||
## Force
|
## Force
|
||||||
@@ -171,11 +147,7 @@ lock.fail.description=A "%s" tárolót nem lehetett zárolni. Győződjön meg a
|
|||||||
migration.title=Széf frissítése
|
migration.title=Széf frissítése
|
||||||
## Start
|
## Start
|
||||||
migration.start.header=Széf frissítése
|
migration.start.header=Széf frissítése
|
||||||
migration.start.text=Hogy megnyissa a "%s" nevű széfét a Cryptomator ezen új verziójában, a széfet frissíteni kell egy újabb formátumra. Mielőtt ezt megteszi, az alábbiakat érdemes figyelembe vennie:
|
|
||||||
migration.start.remarkUndone=Ezt a módosítást nem lehet visszafordítani.
|
migration.start.remarkUndone=Ezt a módosítást nem lehet visszafordítani.
|
||||||
migration.start.remarkVersions=A Cryptomator régebbi verziói nem fogják tudni megnyitni a frissített széfet.
|
|
||||||
migration.start.remarkCanRun=Meg kell győződnie arról, hogy minden eszköz, amelyről eléri ezt a széfet képes futtatni a Cryptomator ezen verzióját.
|
|
||||||
migration.start.remarkSynced=Meg kell győződnie arról, hogy a széfe teljesen szinkronizálva van ezen és az összes többi eszközön a frissítés előtt.
|
|
||||||
migration.start.confirm=Elolvastam és megértettem a fenti információkat
|
migration.start.confirm=Elolvastam és megértettem a fenti információkat
|
||||||
## Run
|
## Run
|
||||||
migration.run.enterPassword=Írja be a jelszót a következőhöz Enter the password for "%s"
|
migration.run.enterPassword=Írja be a jelszót a következőhöz Enter the password for "%s"
|
||||||
@@ -233,16 +205,10 @@ health.result.severityFilter.good=Rendben
|
|||||||
health.result.severityFilter.info=Infó
|
health.result.severityFilter.info=Infó
|
||||||
health.result.severityFilter.warn=Figyelmeztetés
|
health.result.severityFilter.warn=Figyelmeztetés
|
||||||
health.result.severityFilter.crit=Kritikus
|
health.result.severityFilter.crit=Kritikus
|
||||||
health.result.severityTip.good=Súlyosság: Jó\nNormális séf struktúra.
|
|
||||||
health.result.severityTip.info=Súlyosság: Info\nA széf struktúrája ép, javítás ajánlott.
|
|
||||||
health.result.severityTip.warn=Súlyosság: Figyelmeztetés\nA széf struktúrája sérült, javítás erősen ajánlott.
|
|
||||||
health.result.severityTip.crit=Súlyosság: Kritikus\nA széf struktúrája sérült, adatvesztés áll fönt.
|
|
||||||
health.result.fixStateFilter.all=Javítás státusz - Mind
|
|
||||||
health.result.fixStateFilter.fixable=Javítható
|
health.result.fixStateFilter.fixable=Javítható
|
||||||
health.result.fixStateFilter.notFixable=Nem javítható
|
health.result.fixStateFilter.notFixable=Nem javítható
|
||||||
health.result.fixStateFilter.fixing=Javítás alatt…
|
health.result.fixStateFilter.fixing=Javítás alatt…
|
||||||
health.result.fixStateFilter.fixed=Kijavított
|
health.result.fixStateFilter.fixed=Kijavított
|
||||||
health.result.fixStateFilter.fixFailed=Sikertelen javítás
|
|
||||||
## Fix Application
|
## Fix Application
|
||||||
health.fix.fixBtn=Javítás
|
health.fix.fixBtn=Javítás
|
||||||
health.fix.successTip=Javítás sikeres
|
health.fix.successTip=Javítás sikeres
|
||||||
@@ -253,7 +219,6 @@ preferences.title=Beállítások
|
|||||||
## General
|
## General
|
||||||
preferences.general=Általános
|
preferences.general=Általános
|
||||||
preferences.general.startHidden=Az ablak elrejtése a Cryptomator indítása után
|
preferences.general.startHidden=Az ablak elrejtése a Cryptomator indítása után
|
||||||
preferences.general.autoCloseVaults=A széfek automatikus lezárása az alkalmazás bezárásakor
|
|
||||||
preferences.general.debugLogging=Hibakeresési naplózás engedélyezése
|
preferences.general.debugLogging=Hibakeresési naplózás engedélyezése
|
||||||
preferences.general.debugDirectory=Naplófájlok megjelenítése
|
preferences.general.debugDirectory=Naplófájlok megjelenítése
|
||||||
preferences.general.autoStart=Cryptomator indítása a rendszerrel együtt
|
preferences.general.autoStart=Cryptomator indítása a rendszerrel együtt
|
||||||
@@ -274,17 +239,7 @@ preferences.interface.showMinimizeButton=Kicsinyítés ikon megjelenítése
|
|||||||
preferences.interface.showTrayIcon=Tálca ikon megjelenítése (újraindítás szükséges)
|
preferences.interface.showTrayIcon=Tálca ikon megjelenítése (újraindítás szükséges)
|
||||||
## Volume
|
## Volume
|
||||||
preferences.volume=Virtuális meghajtó
|
preferences.volume=Virtuális meghajtó
|
||||||
preferences.volume.type=Kötet Típusa
|
|
||||||
preferences.volume.type.automatic=Automatikus
|
preferences.volume.type.automatic=Automatikus
|
||||||
preferences.volume.docsTooltip=További információért a kötet típusokról kattintson ide, hogy megnyissa a dokumentációt.
|
|
||||||
preferences.volume.fuseRestartRequired=A változtatások alkalmazásához újra kell indítania a Cryptomatort.
|
|
||||||
preferences.volume.tcp.port=TCP Port
|
|
||||||
preferences.volume.supportedFeatures=A kiválaszott kötet típus az alábbi funkciókat támogatja:
|
|
||||||
preferences.volume.feature.mountAuto=Automatikus csatlakozási pont választás
|
|
||||||
preferences.volume.feature.mountToDir=Egyéni mappa csatlakozási pontként
|
|
||||||
preferences.volume.feature.mountToDriveLetter=Meghajtó betűjel csatolási pontként
|
|
||||||
preferences.volume.feature.mountFlags=Egyéni csatolási opciók
|
|
||||||
preferences.volume.feature.readOnly=Csak olvasható csatolás
|
|
||||||
## Updates
|
## Updates
|
||||||
preferences.updates=Frissítések
|
preferences.updates=Frissítések
|
||||||
preferences.updates.currentVersion=Jelenlegi verzió: %s
|
preferences.updates.currentVersion=Jelenlegi verzió: %s
|
||||||
@@ -307,34 +262,26 @@ stats.title=Statisztika ehhez %s
|
|||||||
stats.cacheHitRate=Gyorsítótár találati arány
|
stats.cacheHitRate=Gyorsítótár találati arány
|
||||||
## Read
|
## Read
|
||||||
stats.read.throughput.idle=Olvasás: tétlen
|
stats.read.throughput.idle=Olvasás: tétlen
|
||||||
stats.read.throughput.kibs=Olvasás: %.2f KiB/s
|
|
||||||
stats.read.throughput.mibs=Olvasás: %.2f MiB/s
|
stats.read.throughput.mibs=Olvasás: %.2f MiB/s
|
||||||
stats.read.total.data.none=Olvasott adat: -
|
stats.read.total.data.none=Olvasott adat: -
|
||||||
stats.read.total.data.kib=Adat beolvasva: %.1f KiB
|
|
||||||
stats.read.total.data.mib=Olvasott adat: %.1f MiB
|
stats.read.total.data.mib=Olvasott adat: %.1f MiB
|
||||||
stats.read.total.data.gib=Olvasott adat: %.1f GiB
|
stats.read.total.data.gib=Olvasott adat: %.1f GiB
|
||||||
stats.decr.total.data.none=Dekódolt adat: -
|
stats.decr.total.data.none=Dekódolt adat: -
|
||||||
stats.decr.total.data.kib=Adat visszafejtve: %.1f KiB
|
|
||||||
stats.decr.total.data.mib=Dekódolt adat: %.1f MiB
|
stats.decr.total.data.mib=Dekódolt adat: %.1f MiB
|
||||||
stats.decr.total.data.gib=Dekódolt adat: %.1f GiB
|
stats.decr.total.data.gib=Dekódolt adat: %.1f GiB
|
||||||
stats.read.accessCount=Összes olvasás: %d
|
stats.read.accessCount=Összes olvasás: %d
|
||||||
## Write
|
## Write
|
||||||
stats.write.throughput.idle=Írás: tétlen
|
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.throughput.mibs=Írás: %.2f MiB/s
|
||||||
stats.write.total.data.none=Írva: -
|
stats.write.total.data.none=Írva: -
|
||||||
stats.write.total.data.kib=Írt adatok: %.1f KiB
|
|
||||||
stats.write.total.data.mib=Írott adat: %.1f MiB
|
stats.write.total.data.mib=Írott adat: %.1f MiB
|
||||||
stats.write.total.data.gib=Írott adat: %.1f GiB
|
stats.write.total.data.gib=Írott adat: %.1f GiB
|
||||||
stats.encr.total.data.none=Titkosított adat: -
|
stats.encr.total.data.none=Titkosított adat: -
|
||||||
stats.encr.total.data.kib=Titkosított adatok: %.1f KiB
|
|
||||||
stats.encr.total.data.mib=Titkosított adat: %.1f MiB
|
stats.encr.total.data.mib=Titkosított adat: %.1f MiB
|
||||||
stats.encr.total.data.gib=Titkosított adat: %.1f GiB
|
stats.encr.total.data.gib=Titkosított adat: %.1f GiB
|
||||||
stats.write.accessCount=Összes írás: %d
|
stats.write.accessCount=Összes írás: %d
|
||||||
|
|
||||||
## Accesses
|
## Accesses
|
||||||
stats.access.current=Hozzáférések: %d
|
|
||||||
stats.access.total=Összes hozzáférés: %d
|
|
||||||
|
|
||||||
|
|
||||||
# Main Window
|
# Main Window
|
||||||
@@ -365,18 +312,12 @@ main.vaultDetail.passwordSavedInKeychain=Jelszó mentve
|
|||||||
main.vaultDetail.unlockedStatus=FELOLDVA
|
main.vaultDetail.unlockedStatus=FELOLDVA
|
||||||
main.vaultDetail.accessLocation=A széf tartalma itt érhető el:
|
main.vaultDetail.accessLocation=A széf tartalma itt érhető el:
|
||||||
main.vaultDetail.revealBtn=Széf megjelenítése
|
main.vaultDetail.revealBtn=Széf megjelenítése
|
||||||
main.vaultDetail.copyUri=URI másolása
|
|
||||||
main.vaultDetail.lockBtn=Zárolás
|
main.vaultDetail.lockBtn=Zárolás
|
||||||
main.vaultDetail.bytesPerSecondRead=Olvasás:
|
main.vaultDetail.bytesPerSecondRead=Olvasás:
|
||||||
main.vaultDetail.bytesPerSecondWritten=Írás:
|
main.vaultDetail.bytesPerSecondWritten=Írás:
|
||||||
main.vaultDetail.throughput.idle=tétlen
|
main.vaultDetail.throughput.idle=tétlen
|
||||||
main.vaultDetail.throughput.kbps=%.1f KiB/s
|
|
||||||
main.vaultDetail.throughput.mbps=%.1f MiB/s
|
main.vaultDetail.throughput.mbps=%.1f MiB/s
|
||||||
main.vaultDetail.stats=Széf statisztika
|
main.vaultDetail.stats=Széf statisztika
|
||||||
main.vaultDetail.locateEncryptedFileBtn=Titkosított fájl megkeresése
|
|
||||||
main.vaultDetail.locateEncryptedFileBtn.tooltip=Válasszon a széfből egy fájlt a titkosított megfelelőjének megkereséséhez
|
|
||||||
main.vaultDetail.encryptedPathsCopied=Az útvonal a vágólapra került!
|
|
||||||
main.vaultDetail.filePickerTitle=Fájl választása a széfben
|
|
||||||
### Missing
|
### Missing
|
||||||
main.vaultDetail.missing.info=A Cryptomator nem talált széfet ezen az útvonalon.
|
main.vaultDetail.missing.info=A Cryptomator nem talált széfet ezen az útvonalon.
|
||||||
main.vaultDetail.missing.recheck=Ellenőrizze újra
|
main.vaultDetail.missing.recheck=Ellenőrizze újra
|
||||||
@@ -415,56 +356,36 @@ vaultOptions.general.startHealthCheckBtn=Épség-ellenőrzés indítása
|
|||||||
|
|
||||||
## Mount
|
## Mount
|
||||||
vaultOptions.mount=Felcsatolás
|
vaultOptions.mount=Felcsatolás
|
||||||
vaultOptions.mount.info=Az opciók a kiválasztott kötet típustól függőek.
|
|
||||||
vaultOptions.mount.linkToPreferences=Virtuális meghajtó opciók megnyitása
|
|
||||||
vaultOptions.mount.readonly=Csak-olvasható
|
vaultOptions.mount.readonly=Csak-olvasható
|
||||||
vaultOptions.mount.customMountFlags=Egyedi csatolási paraméterek
|
vaultOptions.mount.customMountFlags=Egyedi csatolási paraméterek
|
||||||
vaultOptions.mount.winDriveLetterOccupied=foglalt
|
vaultOptions.mount.winDriveLetterOccupied=foglalt
|
||||||
vaultOptions.mount.mountPoint=Csatolási pont
|
vaultOptions.mount.mountPoint=Csatolási pont
|
||||||
vaultOptions.mount.mountPoint.auto=Válasszon egy megfelelő helyet automatikusan
|
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.driveLetter=Használja a kiválasztott meghajtó betűjelét
|
||||||
vaultOptions.mount.mountPoint.custom=Egyéni könyvtár használata
|
|
||||||
vaultOptions.mount.mountPoint.directoryPickerButton=Kiválaszt…
|
vaultOptions.mount.mountPoint.directoryPickerButton=Kiválaszt…
|
||||||
vaultOptions.mount.mountPoint.directoryPickerTitle=Válasszon könyvtárat
|
|
||||||
## Master Key
|
## Master Key
|
||||||
vaultOptions.masterkey=Jelszó
|
vaultOptions.masterkey=Jelszó
|
||||||
vaultOptions.masterkey.changePasswordBtn=Jelszó megváltoztatása
|
vaultOptions.masterkey.changePasswordBtn=Jelszó megváltoztatása
|
||||||
vaultOptions.masterkey.forgetSavedPasswordBtn=Mentett jelszó törlése
|
vaultOptions.masterkey.forgetSavedPasswordBtn=Mentett jelszó törlése
|
||||||
vaultOptions.masterkey.recoveryKeyExplanation=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.recoveryKeyExplanation=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.showRecoveryKeyBtn=Visszaállítási kulcs megjelenítése
|
||||||
vaultOptions.masterkey.recoverPasswordBtn=Jelszó visszaállítása
|
|
||||||
## Hub
|
## Hub
|
||||||
vaultOptions.hub=Helyreállítás
|
|
||||||
vaultOptions.hub.convertInfo=Ezen visszaállítási kulcs segítségével átváltoztathatja ezt a Hub széfet egy jelszó-alapú széffé vészhelyzet esetén.
|
|
||||||
vaultOptions.hub.convertBtn=Jelszó-alapú széffé alakítás
|
|
||||||
|
|
||||||
# Recovery Key
|
# Recovery Key
|
||||||
## Display Recovery Key
|
## Display Recovery Key
|
||||||
recoveryKey.display.title=Visszaállítási kulcs mutatása
|
|
||||||
recoveryKey.create.message=Jelszó szükséges
|
|
||||||
recoveryKey.create.description=Írja be a jelszavát a "%s" visszaállítási kulcsának megjelenítéséhez:
|
recoveryKey.create.description=Írja be a jelszavát a "%s" visszaállítási kulcsának megjelenítéséhez:
|
||||||
recoveryKey.display.description=A következő helyreállítási kulcs használható a "%s" hozzáférésének visszaállítására:
|
recoveryKey.display.description=A következő helyreállítási kulcs használható a "%s" hozzáférésének visszaállítására:
|
||||||
recoveryKey.display.StorageHints=Tartsa nagyon biztonságos helyen. pl.:\n •Tárolja egy jelszókezelővel\n •Mentse el egy USB meghajtóra\n •Nyomtassa egy papírra
|
recoveryKey.display.StorageHints=Tartsa nagyon biztonságos helyen. pl.:\n •Tárolja egy jelszókezelővel\n •Mentse el egy USB meghajtóra\n •Nyomtassa egy papírra
|
||||||
## Reset Password
|
## Reset Password
|
||||||
### Enter Recovery Key
|
### Enter Recovery Key
|
||||||
recoveryKey.recover.title=Jelszó visszaállítása
|
|
||||||
recoveryKey.recover.prompt=Írja be a visszaállítási kulcsot a következőhöz "%s":
|
|
||||||
recoveryKey.recover.correctKey=Ez a visszaállítási kulcs érvényes
|
recoveryKey.recover.correctKey=Ez a visszaállítási kulcs érvényes
|
||||||
recoveryKey.recover.wrongKey=Ez a visszaállítási kulcs egy másik széfhez tartozik
|
recoveryKey.recover.wrongKey=Ez a visszaállítási kulcs egy másik széfhez tartozik
|
||||||
recoveryKey.recover.invalidKey=Ez a visszaállítási kulcs nem érvényes
|
recoveryKey.recover.invalidKey=Ez a visszaállítási kulcs nem érvényes
|
||||||
recoveryKey.printout.heading=Cryptomator visszaállítási kulcs\n"%s"\n
|
recoveryKey.printout.heading=Cryptomator visszaállítási kulcs\n"%s"\n
|
||||||
### Reset Password
|
### Reset Password
|
||||||
recoveryKey.recover.resetBtn=Visszaállítás
|
|
||||||
### Recovery Key Password Reset Success
|
### Recovery Key Password Reset Success
|
||||||
recoveryKey.recover.resetSuccess.message=A jelszó alaphelyzetbe állítása sikeresen megtörtént
|
|
||||||
recoveryKey.recover.resetSuccess.description=Feloldhatja a széfet az új jelszóval.
|
|
||||||
|
|
||||||
# Convert Vault
|
# Convert Vault
|
||||||
convertVault.title=Széf átalakítása
|
|
||||||
convertVault.convert.convertBtn.before=Átalakítás
|
|
||||||
convertVault.convert.convertBtn.processing=Átalakítás…
|
|
||||||
convertVault.success.message=Sikeres átalakítás
|
|
||||||
convertVault.hubToPassword.success.description=Feloldhatja a széfet a kiválasztott jelszóval Hub hozzáférés nélkül.
|
|
||||||
|
|
||||||
# New Password
|
# New Password
|
||||||
newPassword.promptText=Adjon meg egy új jelszót
|
newPassword.promptText=Adjon meg egy új jelszót
|
||||||
@@ -479,12 +400,6 @@ passwordStrength.messageLabel.3=Erős
|
|||||||
passwordStrength.messageLabel.4=Nagyon erős
|
passwordStrength.messageLabel.4=Nagyon erős
|
||||||
|
|
||||||
# Quit
|
# Quit
|
||||||
quit.title=Alkalmazás bezárása
|
|
||||||
quit.message=Vannak feloldott széfek
|
|
||||||
quit.description=Kérem, erősítse meg a kilépési szándékát. A Cryptomator lezárja az összes feloldott széfet az adatvesztés elkerülése érdekében.
|
|
||||||
quit.lockAndQuitBtn=Zárolás és kilépés
|
quit.lockAndQuitBtn=Zárolás és kilépés
|
||||||
|
|
||||||
# Forced Quit
|
# Forced Quit
|
||||||
quit.forced.message=Egyes széfeket nem lehetett lezárni
|
|
||||||
quit.forced.description=A széfek zárolását függőbben lévő műveletek vagy megnyitott fájlok blokkolták. Kényszerítheti a maradék széfek zárolását, de az I/O megszakítása nem mentett adatok elvesztéséhez vezethet.
|
|
||||||
quit.forced.forceAndQuitBtn=Kényszerítés és Kilépés
|
|
||||||
@@ -434,7 +434,6 @@ vaultOptions.masterkey.recoveryKeyExplanation=回復キーはパスワードを
|
|||||||
vaultOptions.masterkey.showRecoveryKeyBtn=回復キーを表示
|
vaultOptions.masterkey.showRecoveryKeyBtn=回復キーを表示
|
||||||
vaultOptions.masterkey.recoverPasswordBtn=パスワードをリセット
|
vaultOptions.masterkey.recoverPasswordBtn=パスワードをリセット
|
||||||
## Hub
|
## Hub
|
||||||
vaultOptions.hub=回復
|
|
||||||
|
|
||||||
# Recovery Key
|
# Recovery Key
|
||||||
## Display Recovery Key
|
## Display Recovery Key
|
||||||
@@ -457,10 +456,6 @@ recoveryKey.recover.resetSuccess.message=パスワードをリセットしまし
|
|||||||
recoveryKey.recover.resetSuccess.description=新しいパスワードで金庫の施錠ができます。
|
recoveryKey.recover.resetSuccess.description=新しいパスワードで金庫の施錠ができます。
|
||||||
|
|
||||||
# Convert Vault
|
# Convert Vault
|
||||||
convertVault.title=金庫を変換
|
|
||||||
convertVault.convert.convertBtn.before=変換
|
|
||||||
convertVault.convert.convertBtn.processing=変換中…
|
|
||||||
convertVault.success.message=変換完了
|
|
||||||
|
|
||||||
# New Password
|
# New Password
|
||||||
newPassword.promptText=新しいパスワードを入力してください
|
newPassword.promptText=新しいパスワードを入力してください
|
||||||
|
|||||||
@@ -168,7 +168,6 @@ lock.fail.description=O cofre "%s" não pode ser bloqueado. Certifique-se de que
|
|||||||
migration.title=Atualizar Cofre
|
migration.title=Atualizar Cofre
|
||||||
## Start
|
## Start
|
||||||
migration.start.header=Atualizar Cofre
|
migration.start.header=Atualizar Cofre
|
||||||
migration.start.remarkUndone=Esta atualização não pode ser revertida.
|
|
||||||
migration.start.confirm=Li e entendi as informações acima
|
migration.start.confirm=Li e entendi as informações acima
|
||||||
## Run
|
## Run
|
||||||
migration.run.enterPassword=Introduza a palavra-passe de "%s"
|
migration.run.enterPassword=Introduza a palavra-passe de "%s"
|
||||||
@@ -223,11 +222,8 @@ health.result.severityFilter.good=Ótimo
|
|||||||
health.result.severityFilter.info=Informações
|
health.result.severityFilter.info=Informações
|
||||||
health.result.severityFilter.warn=Atenção
|
health.result.severityFilter.warn=Atenção
|
||||||
health.result.severityFilter.crit=Crítico
|
health.result.severityFilter.crit=Crítico
|
||||||
health.result.fixStateFilter.fixed=Corrigido
|
|
||||||
health.result.fixStateFilter.fixFailed=Falha na correção
|
|
||||||
## Fix Application
|
## Fix Application
|
||||||
health.fix.fixBtn=Corrigir
|
health.fix.fixBtn=Corrigir
|
||||||
health.fix.successTip=Correção bem-sucedida
|
|
||||||
|
|
||||||
# Preferences
|
# Preferences
|
||||||
preferences.title=Preferências
|
preferences.title=Preferências
|
||||||
@@ -235,7 +231,6 @@ preferences.title=Preferências
|
|||||||
preferences.general=Geral
|
preferences.general=Geral
|
||||||
preferences.general.startHidden=Ocultar janela ao iniciar o Cryptomator
|
preferences.general.startHidden=Ocultar janela ao iniciar o Cryptomator
|
||||||
preferences.general.autoCloseVaults=Bloquear cofres abertos automaticamente ao sair da aplicação
|
preferences.general.autoCloseVaults=Bloquear cofres abertos automaticamente ao sair da aplicação
|
||||||
preferences.general.keychainBackend=Guardar palavras-passe com
|
|
||||||
## Interface
|
## Interface
|
||||||
preferences.interface=Interface
|
preferences.interface=Interface
|
||||||
preferences.interface.theme=Aspecto e Ambiente
|
preferences.interface.theme=Aspecto e Ambiente
|
||||||
@@ -251,9 +246,7 @@ preferences.interface.interfaceOrientation.rtl=Da direita para a esquerda
|
|||||||
preferences.interface.showMinimizeButton=Mostrar botão de minimização
|
preferences.interface.showMinimizeButton=Mostrar botão de minimização
|
||||||
## Volume
|
## Volume
|
||||||
preferences.volume=Unidade Virtual
|
preferences.volume=Unidade Virtual
|
||||||
preferences.volume.type=Tipo de Volume
|
|
||||||
preferences.volume.type.automatic=Automático
|
preferences.volume.type.automatic=Automático
|
||||||
preferences.volume.feature.readOnly=Volume apenas-leitura
|
|
||||||
## Updates
|
## Updates
|
||||||
preferences.updates=Atualizações
|
preferences.updates=Atualizações
|
||||||
preferences.updates.currentVersion=Versão atual: %s
|
preferences.updates.currentVersion=Versão atual: %s
|
||||||
@@ -262,10 +255,6 @@ preferences.updates.checkNowBtn=Verificar Agora
|
|||||||
preferences.updates.updateAvailable=Atualização para a versão %s disponível.
|
preferences.updates.updateAvailable=Atualização para a versão %s disponível.
|
||||||
## Contribution
|
## Contribution
|
||||||
preferences.contribute=Apoie-nos
|
preferences.contribute=Apoie-nos
|
||||||
preferences.contribute.registeredFor=Certificado de apoiador registado para %s
|
|
||||||
preferences.contribute.noCertificate=Apoie o Cryptomator e receba um certificado de apoiador. É como uma chave de licença, mas para pessoas incríveis a usar um software gratuito. ;-)
|
|
||||||
preferences.contribute.getCertificate=Não o tem? Saiba como pode obtê-lo.
|
|
||||||
preferences.contribute.promptText=Insira o código do certificado de apoiador aqui
|
|
||||||
#<-- Add entries for donations and code/translation/documentation contribution -->
|
#<-- Add entries for donations and code/translation/documentation contribution -->
|
||||||
|
|
||||||
## About
|
## About
|
||||||
|
|||||||
@@ -154,8 +154,6 @@ hub.registerFailed.description=Ocorreu um erro no processo de nomeação do disp
|
|||||||
hub.unauthorized.message=Acesso negado
|
hub.unauthorized.message=Acesso negado
|
||||||
hub.unauthorized.description=Seu dispositivo ainda não foi autorizado a acessar este cofre. Peça ao proprietário ou a um administrador deste cofre para autorizá-lo.
|
hub.unauthorized.description=Seu dispositivo ainda não foi autorizado a acessar este cofre. Peça ao proprietário ou a um administrador deste cofre para autorizá-lo.
|
||||||
### License Exceeded
|
### License Exceeded
|
||||||
hub.invalidLicense.message=Licença Invalida
|
|
||||||
hub.invalidLicense.description=Sua instância do Cryptomator Hub possui uma licença inválida. Por favor, informe um administrador do Hub para atualizar ou renovar a licença.
|
|
||||||
|
|
||||||
# Lock
|
# Lock
|
||||||
## Force
|
## Force
|
||||||
@@ -274,10 +272,7 @@ preferences.interface.showMinimizeButton=Mostrar botão minimizar
|
|||||||
preferences.interface.showTrayIcon=Mostrar ícone na barra do sistema (requer reinicialização)
|
preferences.interface.showTrayIcon=Mostrar ícone na barra do sistema (requer reinicialização)
|
||||||
## Volume
|
## Volume
|
||||||
preferences.volume=Volume Virtual
|
preferences.volume=Volume Virtual
|
||||||
preferences.volume.type=Tipo de Volume
|
|
||||||
preferences.volume.type.automatic=Automático
|
preferences.volume.type.automatic=Automático
|
||||||
preferences.volume.docsTooltip=Abra a documentação para saber mais sobre os diferentes tipos de volumes.
|
|
||||||
preferences.volume.fuseRestartRequired=Para aplicar as mudanças, o Cryptomator precisa ser reiniciado.
|
|
||||||
preferences.volume.tcp.port=Porta TCP
|
preferences.volume.tcp.port=Porta TCP
|
||||||
preferences.volume.supportedFeatures=O tipo de volume escolhido suporta os seguintes recursos:
|
preferences.volume.supportedFeatures=O tipo de volume escolhido suporta os seguintes recursos:
|
||||||
preferences.volume.feature.mountAuto=Seleção automática de ponto de montagem
|
preferences.volume.feature.mountAuto=Seleção automática de ponto de montagem
|
||||||
@@ -307,27 +302,21 @@ stats.title=Estatísticas para %s
|
|||||||
stats.cacheHitRate=Taxa de Utilização do Cache
|
stats.cacheHitRate=Taxa de Utilização do Cache
|
||||||
## Read
|
## Read
|
||||||
stats.read.throughput.idle=Leitura: ociosa
|
stats.read.throughput.idle=Leitura: ociosa
|
||||||
stats.read.throughput.kibs=Leitura: %.2f MiB/s
|
|
||||||
stats.read.throughput.mibs=Leitura: %.2f MiB/s
|
stats.read.throughput.mibs=Leitura: %.2f MiB/s
|
||||||
stats.read.total.data.none=Dados lidos: -
|
stats.read.total.data.none=Dados lidos: -
|
||||||
stats.read.total.data.kib=Dados lidos: %.1f GiB
|
|
||||||
stats.read.total.data.mib=Dados lidos: %.1f MiB
|
stats.read.total.data.mib=Dados lidos: %.1f MiB
|
||||||
stats.read.total.data.gib=Dados lidos: %.1f GiB
|
stats.read.total.data.gib=Dados lidos: %.1f GiB
|
||||||
stats.decr.total.data.none=Dados descriptografados: -
|
stats.decr.total.data.none=Dados descriptografados: -
|
||||||
stats.decr.total.data.kib=Dados descriptografados: %.1f GiB
|
|
||||||
stats.decr.total.data.mib=Dados descriptografados: %.1f MiB
|
stats.decr.total.data.mib=Dados descriptografados: %.1f MiB
|
||||||
stats.decr.total.data.gib=Dados descriptografados: %.1f GiB
|
stats.decr.total.data.gib=Dados descriptografados: %.1f GiB
|
||||||
stats.read.accessCount=Total de leituras: %d
|
stats.read.accessCount=Total de leituras: %d
|
||||||
## Write
|
## Write
|
||||||
stats.write.throughput.idle=Escrita: ociosa
|
stats.write.throughput.idle=Escrita: ociosa
|
||||||
stats.write.throughput.kibs=Escrita: %.2f MiB/s
|
|
||||||
stats.write.throughput.mibs=Escrita: %.2f MiB/s
|
stats.write.throughput.mibs=Escrita: %.2f MiB/s
|
||||||
stats.write.total.data.none=Dados gravados: -
|
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.mib=Dados gravados: %.1f MiB
|
||||||
stats.write.total.data.gib=Dados gravados: %.1f GiB
|
stats.write.total.data.gib=Dados gravados: %.1f GiB
|
||||||
stats.encr.total.data.none=Dados criptografados: -
|
stats.encr.total.data.none=Dados criptografados: -
|
||||||
stats.encr.total.data.kib=Dados encriptados: %.1f KiB
|
|
||||||
stats.encr.total.data.mib=Dados criptografados: %.1f MiB
|
stats.encr.total.data.mib=Dados criptografados: %.1f MiB
|
||||||
stats.encr.total.data.gib=Dados criptografados: %.1f GiB
|
stats.encr.total.data.gib=Dados criptografados: %.1f GiB
|
||||||
stats.write.accessCount=Total gravado: %d
|
stats.write.accessCount=Total gravado: %d
|
||||||
@@ -370,7 +359,6 @@ main.vaultDetail.lockBtn=Bloquear
|
|||||||
main.vaultDetail.bytesPerSecondRead=Leitura:
|
main.vaultDetail.bytesPerSecondRead=Leitura:
|
||||||
main.vaultDetail.bytesPerSecondWritten=Escrita:
|
main.vaultDetail.bytesPerSecondWritten=Escrita:
|
||||||
main.vaultDetail.throughput.idle=ocioso
|
main.vaultDetail.throughput.idle=ocioso
|
||||||
main.vaultDetail.throughput.kbps=%.1f KiB/s
|
|
||||||
main.vaultDetail.throughput.mbps=%.1f MiB/s
|
main.vaultDetail.throughput.mbps=%.1f MiB/s
|
||||||
main.vaultDetail.stats=Estatísticas do Cofre
|
main.vaultDetail.stats=Estatísticas do Cofre
|
||||||
main.vaultDetail.locateEncryptedFileBtn=Localizar Arquivo Criptografado
|
main.vaultDetail.locateEncryptedFileBtn=Localizar Arquivo Criptografado
|
||||||
@@ -434,9 +422,6 @@ vaultOptions.masterkey.recoveryKeyExplanation=Se você perder a sua senha, a ún
|
|||||||
vaultOptions.masterkey.showRecoveryKeyBtn=Exibir chave de recuperação
|
vaultOptions.masterkey.showRecoveryKeyBtn=Exibir chave de recuperação
|
||||||
vaultOptions.masterkey.recoverPasswordBtn=Redefinir Senha
|
vaultOptions.masterkey.recoverPasswordBtn=Redefinir Senha
|
||||||
## Hub
|
## Hub
|
||||||
vaultOptions.hub=Recuperação
|
|
||||||
vaultOptions.hub.convertInfo=Você pode usar a chave de recuperação para converter este cofre do Hub em um cofre protegido por senha de emergência.
|
|
||||||
vaultOptions.hub.convertBtn=Converter para Cofre protegido por senha
|
|
||||||
|
|
||||||
# Recovery Key
|
# Recovery Key
|
||||||
## Display Recovery Key
|
## Display Recovery Key
|
||||||
@@ -448,10 +433,7 @@ recoveryKey.display.StorageHints=Mantenha-a em um lugar bem seguro, por exemplo:
|
|||||||
## Reset Password
|
## Reset Password
|
||||||
### Enter Recovery Key
|
### Enter Recovery Key
|
||||||
recoveryKey.recover.title=Redefinir Senha
|
recoveryKey.recover.title=Redefinir Senha
|
||||||
recoveryKey.recover.prompt=Digite a chave de recuperação para "%s":
|
|
||||||
recoveryKey.recover.correctKey=Esta é uma chave de recuperação válida
|
recoveryKey.recover.correctKey=Esta é uma chave de recuperação válida
|
||||||
recoveryKey.recover.wrongKey=Esta chave de recuperação pertence a um outro cofre
|
|
||||||
recoveryKey.recover.invalidKey=Esta chave de recuperação não é válida
|
|
||||||
recoveryKey.printout.heading=Chave de Recuperação do Cryptomator\n"%s"\n
|
recoveryKey.printout.heading=Chave de Recuperação do Cryptomator\n"%s"\n
|
||||||
### Reset Password
|
### Reset Password
|
||||||
recoveryKey.recover.resetBtn=Redefinir
|
recoveryKey.recover.resetBtn=Redefinir
|
||||||
@@ -460,11 +442,6 @@ recoveryKey.recover.resetSuccess.message=Senha redefinida com sucesso
|
|||||||
recoveryKey.recover.resetSuccess.description=Você pode desbloquear o seu cofre com a nova senha.
|
recoveryKey.recover.resetSuccess.description=Você pode desbloquear o seu cofre com a nova senha.
|
||||||
|
|
||||||
# Convert Vault
|
# Convert Vault
|
||||||
convertVault.title=Converter Cofre
|
|
||||||
convertVault.convert.convertBtn.before=Converter
|
|
||||||
convertVault.convert.convertBtn.processing=Convertendo...
|
|
||||||
convertVault.success.message=Conversão bem sucedida
|
|
||||||
convertVault.hubToPassword.success.description=Agora você pode desbloquear o cofre com a senha escolhida sem exigir acesso ao Hub.
|
|
||||||
|
|
||||||
# New Password
|
# New Password
|
||||||
newPassword.promptText=Digite a nova senha
|
newPassword.promptText=Digite a nova senha
|
||||||
|
|||||||
@@ -432,7 +432,6 @@ vaultOptions.masterkey.recoveryKeyExplanation=Kľúč pre obnovu je Vašou jedin
|
|||||||
vaultOptions.masterkey.showRecoveryKeyBtn=Ukázať klúč obnovy
|
vaultOptions.masterkey.showRecoveryKeyBtn=Ukázať klúč obnovy
|
||||||
vaultOptions.masterkey.recoverPasswordBtn=Resetovanie hesla
|
vaultOptions.masterkey.recoverPasswordBtn=Resetovanie hesla
|
||||||
## Hub
|
## Hub
|
||||||
vaultOptions.hub=Obnova
|
|
||||||
|
|
||||||
# Recovery Key
|
# Recovery Key
|
||||||
## Display Recovery Key
|
## Display Recovery Key
|
||||||
@@ -455,10 +454,6 @@ recoveryKey.recover.resetSuccess.message=Heslo úspešne zresetované
|
|||||||
recoveryKey.recover.resetSuccess.description=Môžte odomknúť trezor s novým heslom.
|
recoveryKey.recover.resetSuccess.description=Môžte odomknúť trezor s novým heslom.
|
||||||
|
|
||||||
# Convert Vault
|
# Convert Vault
|
||||||
convertVault.title=Konvertovať trezor
|
|
||||||
convertVault.convert.convertBtn.before=Konvertovať
|
|
||||||
convertVault.convert.convertBtn.processing=Konvertujem…
|
|
||||||
convertVault.success.message=Konverzia úspešná
|
|
||||||
|
|
||||||
# New Password
|
# New Password
|
||||||
newPassword.promptText=Zadajte nové heslo
|
newPassword.promptText=Zadajte nové heslo
|
||||||
|
|||||||
@@ -434,9 +434,6 @@ vaultOptions.masterkey.recoveryKeyExplanation=Bir kurtarma anahtarı şifrenizi
|
|||||||
vaultOptions.masterkey.showRecoveryKeyBtn=Kurtarma Anahtarını Göster
|
vaultOptions.masterkey.showRecoveryKeyBtn=Kurtarma Anahtarını Göster
|
||||||
vaultOptions.masterkey.recoverPasswordBtn=Şifreyi Sıfırla
|
vaultOptions.masterkey.recoverPasswordBtn=Şifreyi Sıfırla
|
||||||
## Hub
|
## Hub
|
||||||
vaultOptions.hub=Kurtarma
|
|
||||||
vaultOptions.hub.convertInfo=Acil bir durumda bu Hub kasasını parola tabanlı bir kasaya dönüştürmek için kurtarma anahtarını kullanabilirsiniz.
|
|
||||||
vaultOptions.hub.convertBtn=Parola Tabanlı Kasaya Dönüştür
|
|
||||||
|
|
||||||
# Recovery Key
|
# Recovery Key
|
||||||
## Display Recovery Key
|
## Display Recovery Key
|
||||||
@@ -448,7 +445,6 @@ recoveryKey.display.StorageHints=Bunu çok güvenli bir yerde saklayın, örneğ
|
|||||||
## Reset Password
|
## Reset Password
|
||||||
### Enter Recovery Key
|
### Enter Recovery Key
|
||||||
recoveryKey.recover.title=Şifreyi Sıfırla
|
recoveryKey.recover.title=Şifreyi Sıfırla
|
||||||
recoveryKey.recover.prompt="%s" için kurtarma anahtarını girin:
|
|
||||||
recoveryKey.recover.correctKey=Bu geçerli bir kurtarma anahtarı
|
recoveryKey.recover.correctKey=Bu geçerli bir kurtarma anahtarı
|
||||||
recoveryKey.recover.wrongKey=Bu kurtarma anahtarı farklı bir kasaya ait
|
recoveryKey.recover.wrongKey=Bu kurtarma anahtarı farklı bir kasaya ait
|
||||||
recoveryKey.recover.invalidKey=Bu kurtarma anahtarı geçerli değil
|
recoveryKey.recover.invalidKey=Bu kurtarma anahtarı geçerli değil
|
||||||
@@ -460,11 +456,6 @@ recoveryKey.recover.resetSuccess.message=Şifre sıfırlama başarılı
|
|||||||
recoveryKey.recover.resetSuccess.description=Yeni şifre ile kasanızın kilidini açabilirsiniz.
|
recoveryKey.recover.resetSuccess.description=Yeni şifre ile kasanızın kilidini açabilirsiniz.
|
||||||
|
|
||||||
# Convert Vault
|
# Convert Vault
|
||||||
convertVault.title=Kasayı Dönüştür
|
|
||||||
convertVault.convert.convertBtn.before=Dönüştür
|
|
||||||
convertVault.convert.convertBtn.processing=Dönüştürülüyor…
|
|
||||||
convertVault.success.message=Dönüştürme başarılı
|
|
||||||
convertVault.hubToPassword.success.description=Artık Hub erişimi gerektirmeden seçilen parola ile kasanın kilidini açabilirsiniz.
|
|
||||||
|
|
||||||
# New Password
|
# New Password
|
||||||
newPassword.promptText=Yeni bir şifre girin
|
newPassword.promptText=Yeni bir şifre girin
|
||||||
|
|||||||
@@ -79,21 +79,17 @@ addvault.new.readme.storageLocation.10=Якщо вам потрібна допо
|
|||||||
addvault.new.readme.accessLocation.fileName=ПРИВІТ.rtf
|
addvault.new.readme.accessLocation.fileName=ПРИВІТ.rtf
|
||||||
addvault.new.readme.accessLocation.1=🔐️ ЗАШИФРОВАНИЙ ТОМ 🔐️
|
addvault.new.readme.accessLocation.1=🔐️ ЗАШИФРОВАНИЙ ТОМ 🔐️
|
||||||
addvault.new.readme.accessLocation.2=Це місце розташування вашого vault.
|
addvault.new.readme.accessLocation.2=Це місце розташування вашого vault.
|
||||||
addvault.new.readme.accessLocation.3=Будь-які файли, додані до цього тому, будуть зашифровані за допомогою Cryptomator. Ви можете працювати із ним як із будь-якою іншою директорією або накопичувачем. Це лише розшифрований вигляд його вмісту, ваші файли завжди знаходяться в зашифрованому вигляді на диску.
|
|
||||||
addvault.new.readme.accessLocation.4=Якщо хочете, то можете видалити цей файл.
|
addvault.new.readme.accessLocation.4=Якщо хочете, то можете видалити цей файл.
|
||||||
## Existing
|
## Existing
|
||||||
addvaultwizard.existing.instruction=Виберіть файл "vault.cryptomator" у вашому існуючому сховищі. Якщо існує лише файл з назвою "masterkey.cryptomator", виберіть його.
|
|
||||||
addvaultwizard.existing.chooseBtn=Обрати…
|
addvaultwizard.existing.chooseBtn=Обрати…
|
||||||
addvaultwizard.existing.filePickerTitle=Виберіть Vault Файл
|
addvaultwizard.existing.filePickerTitle=Виберіть Vault Файл
|
||||||
addvaultwizard.existing.filePickerMimeDesc=Cryptomator Vault
|
addvaultwizard.existing.filePickerMimeDesc=Cryptomator Vault
|
||||||
## Success
|
## Success
|
||||||
addvaultwizard.success.nextStepsInstructions=Додано сховище "%s".\nДля доступу або додавання вмісту це сховище необхідно розблокувати. Також його можна розблокувати й пізніше.
|
|
||||||
addvaultwizard.success.unlockNow=Розблокувати
|
addvaultwizard.success.unlockNow=Розблокувати
|
||||||
|
|
||||||
# Remove Vault
|
# Remove Vault
|
||||||
removeVault.title=Видалити "%s"
|
removeVault.title=Видалити "%s"
|
||||||
removeVault.message=Видалити vault?
|
removeVault.message=Видалити vault?
|
||||||
removeVault.description=Це лише змусить Cryptomator забути про це сховище. Його можна буде додати пізніше. Зашифровані файли на жорсткому диску не будуть видалені.
|
|
||||||
removeVault.confirmBtn=Видалити сховище
|
removeVault.confirmBtn=Видалити сховище
|
||||||
|
|
||||||
# Change Password
|
# Change Password
|
||||||
@@ -123,10 +119,6 @@ unlock.success.description=Вміст vault "%s" тепер доступний
|
|||||||
unlock.success.rememberChoice=Запам'ятайте мій вибір та більше не запитуйте
|
unlock.success.rememberChoice=Запам'ятайте мій вибір та більше не запитуйте
|
||||||
unlock.success.revealBtn=Розкрити Диск
|
unlock.success.revealBtn=Розкрити Диск
|
||||||
## Failure
|
## Failure
|
||||||
unlock.error.customPath.message=Не вдалося змонтувати сховище за вказаним шляхом
|
|
||||||
unlock.error.customPath.description.notSupported=Якщо ви хочете надалі використовувати власний шлях, будь ласка, перейдіть до налаштувань та виберіть тип тому, що його підтримує. В іншому випадку перейдіть до параметрів сховища та оберіть точку монтування, що підтримується.
|
|
||||||
unlock.error.customPath.description.notExists=Вказаний шлях підключення не існує. Створіть його в локальній файловій системі або змініть його в параметрах сховища.
|
|
||||||
unlock.error.customPath.description.generic=Ви створили власний шлях підключення для цього сховища, але скористатися ним не вдалося. Повідомлення про помилку: %s
|
|
||||||
## Hub
|
## Hub
|
||||||
hub.noKeychain.message=Не вдалося отримати доступ до ключа пристрою
|
hub.noKeychain.message=Не вдалося отримати доступ до ключа пристрою
|
||||||
hub.noKeychain.description=Щоб розблокувати Hub vaults, необхідний ключ пристрою, який захищено за допомогою ланцюга ключів. Щоб продовжити, увімкніть “%s” та виберіть ланцюг ключів у налаштуваннях.
|
hub.noKeychain.description=Щоб розблокувати Hub vaults, необхідний ключ пристрою, який захищено за допомогою ланцюга ключів. Щоб продовжити, увімкніть “%s” та виберіть ланцюг ключів у налаштуваннях.
|
||||||
@@ -154,8 +146,6 @@ hub.registerFailed.description=Виникла помилка у процесі
|
|||||||
hub.unauthorized.message=У доступі відмовлено
|
hub.unauthorized.message=У доступі відмовлено
|
||||||
hub.unauthorized.description=Ваш пристрій ще не має прав доступу до цього vault. Попросіть власника vault надати їх.
|
hub.unauthorized.description=Ваш пристрій ще не має прав доступу до цього vault. Попросіть власника vault надати їх.
|
||||||
### License Exceeded
|
### License Exceeded
|
||||||
hub.invalidLicense.message=Недійсна ліцензія Hub
|
|
||||||
hub.invalidLicense.description=У вашого Cryptomator Hub недійсна ліцензія. Будь ласка, повідомте адміністратору Hub, що потрібно оновити або продовжити ліцензію.
|
|
||||||
|
|
||||||
# Lock
|
# Lock
|
||||||
## Force
|
## Force
|
||||||
@@ -334,25 +324,16 @@ vaultOptions.masterkey.recoveryKeyExplanation=У разі втрати паро
|
|||||||
vaultOptions.masterkey.showRecoveryKeyBtn=Показати Ключ Відновлення
|
vaultOptions.masterkey.showRecoveryKeyBtn=Показати Ключ Відновлення
|
||||||
vaultOptions.masterkey.recoverPasswordBtn=Скинути Пароль
|
vaultOptions.masterkey.recoverPasswordBtn=Скинути Пароль
|
||||||
## Hub
|
## Hub
|
||||||
vaultOptions.hub=Відновлення
|
|
||||||
vaultOptions.hub.convertInfo=Ключ відновлення використовується для перетворення цього Hub-сховища на сховище з паролем у надзвичайній ситуації.
|
|
||||||
vaultOptions.hub.convertBtn=Перетворити на сховище з паролем
|
|
||||||
|
|
||||||
# Recovery Key
|
# Recovery Key
|
||||||
## Display Recovery Key
|
## Display Recovery Key
|
||||||
## Reset Password
|
## Reset Password
|
||||||
### Enter Recovery Key
|
### Enter Recovery Key
|
||||||
recoveryKey.recover.title=Скинути Пароль
|
recoveryKey.recover.title=Скинути Пароль
|
||||||
recoveryKey.recover.prompt=Введіть ключ відновлення для "%s:
|
|
||||||
### Reset Password
|
### Reset Password
|
||||||
### Recovery Key Password Reset Success
|
### Recovery Key Password Reset Success
|
||||||
|
|
||||||
# Convert Vault
|
# Convert Vault
|
||||||
convertVault.title=Перетворити сховище
|
|
||||||
convertVault.convert.convertBtn.before=Перетворити
|
|
||||||
convertVault.convert.convertBtn.processing=Перетворення…
|
|
||||||
convertVault.success.message=Перетворення виконано успішно
|
|
||||||
convertVault.hubToPassword.success.description=Тепер ви можете розблокувати сховище за допомогою обраного пароля без необхідності доступу до Hub.
|
|
||||||
|
|
||||||
# New Password
|
# New Password
|
||||||
|
|
||||||
|
|||||||
@@ -1,31 +0,0 @@
|
|||||||
package org.cryptomator.launcher;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.Assertions;
|
|
||||||
import org.junit.jupiter.api.DisplayName;
|
|
||||||
import org.junit.jupiter.params.ParameterizedTest;
|
|
||||||
import org.junit.jupiter.params.provider.MethodSource;
|
|
||||||
|
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.ResourceBundle;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
public class SupportedLanguagesTest {
|
|
||||||
|
|
||||||
@DisplayName("test if resource bundle is localized")
|
|
||||||
@ParameterizedTest(name = "{0}")
|
|
||||||
@MethodSource("languageTags")
|
|
||||||
public void testResourceBundleExists(String tag) {
|
|
||||||
var locale = Locale.forLanguageTag(tag);
|
|
||||||
Assertions.assertNotEquals("und", locale.toLanguageTag(), "Undefined language tag");
|
|
||||||
|
|
||||||
var bundle = Assertions.assertDoesNotThrow(() -> ResourceBundle.getBundle("i18n.strings", locale));
|
|
||||||
|
|
||||||
Assertions.assertEquals(locale, bundle.getLocale());
|
|
||||||
Assertions.assertFalse(bundle.keySet().isEmpty());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Stream<String> languageTags() {
|
|
||||||
return SupportedLanguages.LANGUAGE_TAGS.stream() //
|
|
||||||
.filter(tag -> !"en".equals(tag)); // english uses the default bundle
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -55,4 +55,13 @@
|
|||||||
<cve>CVE-2022-45688</cve>
|
<cve>CVE-2022-45688</cve>
|
||||||
</suppress>
|
</suppress>
|
||||||
|
|
||||||
|
<suppress>
|
||||||
|
<notes><![CDATA[
|
||||||
|
Suppress false positive, because com.google.common.io.Files.getTempDir() is not used
|
||||||
|
]]></notes>
|
||||||
|
<packageUrl regex="true">^pkg:maven/com\.google\.guava/guava@.*$</packageUrl>
|
||||||
|
<vulnerabilityName>CVE-2020-8908</vulnerabilityName>
|
||||||
|
<cve>CVE-2020-8908</cve>
|
||||||
|
</suppress>
|
||||||
|
|
||||||
</suppressions>
|
</suppressions>
|
||||||
Reference in New Issue
Block a user