Compare commits

..
Author SHA1 Message Date
Armin Schrenk 9a0c03eacc unify arch naming convention and generalize publish file-matching-regex 2025-06-11 11:59:12 +02:00
Armin Schrenk ab10a139a7 adjustments for local build script 2025-06-11 11:41:16 +02:00
Armin Schrenk 1184ba6748 fix winget 2025-06-11 11:40:53 +02:00
Armin Schrenk b1bf84a332 dedup setup-java action 2025-06-11 11:40:46 +02:00
Ralph Plawetzki 9397cbf18a Support Windows ARM64 2025-06-07 08:31:05 +02:00
354225bf1e Switch on Windows Hello (#3808)
---------

Co-authored-by: Armin Schrenk <armin.schrenk@skymatic.de>
2025-06-04 11:25:45 +02:00
Armin Schrenk 0d4f373311 enable native access for javafx.graphics during tests
references #3882
2025-06-03 16:52:31 +02:00
Armin Schrenk 1da535e89c don't trigger distribution builds for dependabot 2025-06-03 16:25:13 +02:00
Armin SchrenkandGitHub 941b4e3652 Feature: JavaFX 24 (#3882) 2025-06-03 15:51:37 +02:00
Armin Schrenk dd1af8cd78 add migration for renamed SecretServiceKeychainAccess
references #3877
2025-06-03 15:49:40 +02:00
Armin Schrenk 27ea29ab9d fix IllegalArguemntException
do not try to convert a path which is already an OS path
2025-06-03 13:57:08 +02:00
Armin SchrenkandGitHub a699a794a9 CI: Trigger the appropiate build workflows based on changed files (#3880) 2025-06-02 16:57:30 +02:00
Armin SchrenkandGitHub cd6b1cf129 Update README.md
bump JDK build dependency to 24
2025-06-02 12:08:24 +02:00
Armin SchrenkandGitHub 7d2c4992af update pom and adjust classes to new keychain api. (#3877) 2025-06-02 10:28:52 +02:00
Armin SchrenkandGitHub 6a21d24687 Merge pull request #3863 from cryptomator/feature/jdk-24
Feature: JDK 24
2025-05-22 15:41:53 +02:00
Armin Schrenk cba6ed9875 Merge branch 'develop' into feature/jdk-24 2025-05-21 16:08:38 +02:00
Armin Schrenk 72fdc8f536 [skip ci] allow manual trigger for building macOS x64 dmg 2025-05-21 14:41:48 +02:00
Armin Schrenk 41336cca13 bump to JDK 24 in all java workflows 2025-05-21 13:08:55 +02:00
Armin Schrenk 322907bbcd bump minimal ubuntu version Cryptomator is build on 2025-05-21 13:05:59 +02:00
Armin Schrenk 1f8df6fead fix comparsion to undefined variable 2025-05-21 13:01:54 +02:00
Armin Schrenk 6e085b783d use correct bash syntax to check exit code 2025-05-21 13:01:33 +02:00
Armin Schrenk 59dddd3f4c [skip ci] increase the required build version for coffeelibs to ppa3 build 2025-05-21 12:04:50 +02:00
Armin Schrenk d6bbcfbbc1 Revert "[skip ci] coffeelibs jdk is built with JEP 493"
This reverts commit 0a0dde3f47.
2025-05-21 11:50:55 +02:00
Armin Schrenk 7260d7f9f8 fixes #3847 2025-05-19 12:20:04 +02:00
Armin Schrenk c39c4be1cd Merge branch 'main' into develop
# Conflicts:
#	pom.xml
2025-05-15 08:59:15 +02:00
Tobias Hagemann 565ab4a09b Merge branch 'hotfix/1.16.2' 2025-05-15 08:47:31 +02:00
Armin Schrenk f797491a17 prepare 1.16.2 2025-05-15 00:50:12 +02:00
Armin Schrenk cff83b6ac6 closes #3852 2025-05-15 00:47:35 +02:00
Armin Schrenk 6f9b3e31e7 [skip ci] prevent gpg from pruning the key cache 2025-05-15 00:27:30 +02:00
Armin Schrenk 0a0dde3f47 [skip ci] coffeelibs jdk is built with JEP 493 2025-05-13 15:22:39 +02:00
Armin Schrenk e27e303c01 [skip ci] use JDK 24 also for deb build 2025-05-13 14:12:07 +02:00
Armin Schrenk ef54b685f6 [skip ci] fix wrong logic to determine linkable runtime image in local build scripts 2025-05-08 16:51:04 +02:00
Jan-Peter Klein 0370fd5848 fix minWidth and minHeight 2025-05-08 11:14:10 +02:00
Armin Schrenk 119d18d699 [skip ci] cleanup 2025-05-08 11:08:02 +02:00
Armin Schrenk 8322633b14 apply workaround for wix burn bug 2025-05-08 11:04:59 +02:00
Armin Schrenk 2f32fc5c16 [skip ci] use different working directory for building the exe 2025-05-07 17:23:52 +02:00
Armin Schrenk 7c44c4f194 fix wrong logic in build scripts 2025-05-07 16:59:36 +02:00
Armin Schrenk bbb663f9d2 update windows ci workflow to wix 6 2025-05-07 12:47:48 +02:00
Armin Schrenk fdb4a2fb5c remove wix version pinning 2025-05-07 12:17:43 +02:00
Armin Schrenk 0a4684133d update ci to JDK 24 2025-05-07 12:17:27 +02:00
Armin Schrenk 0d5e518af3 adjust jlink to JEP 493 2025-05-07 12:16:52 +02:00
Armin Schrenk d47ab43fcf add launch feature to exe installer 2025-05-06 17:01:13 +02:00
Armin Schrenk 19a711d12b migrate wix burn bundle to wix 6 2025-05-06 17:00:17 +02:00
Armin Schrenk bf2db55d00 switch to ubuntu 22.04 (jammy) when deploying to launchpad 2025-05-02 13:49:41 +02:00
Armin Schrenk 885975e099 [skip ci] Merge branch 'main' into develop 2025-04-30 14:05:40 +02:00
Armin Schrenk 85c2901484 Merge branch 'release/1.16.1' 2025-04-30 14:04:43 +02:00
Armin Schrenk 434030b139 finalize 1.16.1 2025-04-30 14:04:32 +02:00
Armin Schrenk e43bb37758 prepare 1.16.1 2025-04-30 12:12:59 +02:00
Armin Schrenk 2eb9f0fca8 Fixes #3838 2025-04-30 12:12:04 +02:00
Armin SchrenkandGitHub 9503feb9c4 Feature: Use user and system certificate stores on macOS (#3837) 2025-04-29 17:02:14 +02:00
Armin Schrenk 08e9f130e4 [skip ci] Merge branch 'main' into develop 2025-04-29 11:28:38 +02:00
Armin Schrenk 4e39eaa1f1 Merge branch 'release/1.16.0' 2025-04-29 11:27:56 +02:00
Armin Schrenk eaca95e8dc finalize 1.16.0 2025-04-29 11:27:44 +02:00
Armin Schrenk cf32e794c8 Merge branch 'develop' into release/1.16.0 2025-04-29 11:26:48 +02:00
Armin Schrenk b5b221a5c7 remove manual wix installation from ci 2025-04-29 11:15:13 +02:00
CryptobotandGitHub d7cb99a12d New Crowdin updates (#3819)
New translations strings.properties

Chinese Traditional; Dutch; French; Hebrew; Italian; Latvian; Persian; Portuguese; Portuguese, Brazilian; Russian; Slovak; Spanish; Swedish; 

[ci skip]
2025-04-29 10:55:33 +02:00
Armin Schrenk b1893c63d4 Bump cryptofs from version 2.9.0-beta2 to 2.9.0 2025-04-28 13:00:21 +02:00
Armin Schrenk 79b3274074 migrate to wix6
* drop custom dialogs in installer
2025-04-24 15:56:02 +02:00
Armin Schrenk 7c86e5e39a update pom to use JDK 24 2025-04-24 15:53:17 +02:00
Armin Schrenk b50cc703b6 Merge branch 'develop' into release/1.16.0 2025-04-15 13:46:30 +02:00
Armin Schrenk 9dc4a1dc5a [skip ci] update distribution build files to jfx 23.0.2 2025-04-15 13:45:14 +02:00
Armin Schrenk f1a63a1679 update debian workflow to use JDK 23.0.2 2025-04-15 13:42:49 +02:00
Armin Schrenk d53d4e3452 Merge branch 'develop' into release/1.16.0 2025-04-15 11:42:17 +02:00
Armin Schrenk b7fa1ae6d8 Merge branch 'develop' into release/1.16.0
# Conflicts:
#	src/main/java/org/cryptomator/common/vaults/Vault.java
#	src/main/java/org/cryptomator/ui/eventview/EventListCellController.java
#	src/main/java/org/cryptomator/ui/eventview/EventListCellFactory.java
#	src/main/java/org/cryptomator/ui/eventview/EventViewController.java
#	src/main/java/org/cryptomator/ui/eventview/EventViewModule.java
#	src/main/java/org/cryptomator/ui/mainwindow/VaultDetailUnlockedController.java
#	src/main/java/org/cryptomator/ui/mainwindow/VaultListController.java
#	src/main/resources/css/dark_theme.css
#	src/main/resources/css/light_theme.css
#	src/main/resources/fxml/eventview.fxml
#	src/main/resources/fxml/vault_detail_unlocked.fxml
#	src/main/resources/fxml/vault_list.fxml
#	src/main/resources/i18n/strings.properties
2025-04-15 11:41:39 +02:00
CryptobotandGitHub 3f192a587c New Crowdin updates (#3725)
New translations strings.properties

Afrikaans; Arabic; Bashkir; Belarusian; Bengali; Bosnian; Bulgarian; Catalan; Chinese Simplified; Chinese Traditional; Chinese Traditional, Hong Kong; Croatian; Czech; Danish; Dutch; Filipino; Finnish; French; Galician; German; Greek; Hebrew; Hindi; Hungarian; Indonesian; Italian; Japanese; Korean; Latvian; Macedonian; Marathi; Norwegian; Norwegian Bokmal; Norwegian Nynorsk; Persian; Polish; Portuguese; Portuguese, Brazilian; Punjabi; Romanian; Russian; Serbian (Cyrillic); Serbian (Latin); Sinhala; Slovak; Slovenian; Spanish; Swahili, Tanzania; Swedish; Tamil; Telugu; Thai; Turkish; Ukrainian; Urdu (Pakistan); Uyghur; Vietnamese; 

[ci skip]
2025-04-15 11:31:16 +02:00
Armin Schrenk 3a1b0b17d6 fix translations 2025-04-15 11:23:46 +02:00
dependabot[bot]andGitHub 5d2a243c55 Bump the java-test-dependencies group across 1 directory with 2 updates (#3776) 2025-04-15 08:59:50 +00:00
dependabot[bot]andGitHub 008a2a3301 Bump the java-production-dependencies group with 4 updates (#3796) 2025-04-15 08:59:01 +00:00
Armin Schrenk 0680437004 Set a mininum width for the vault choice box in the event view 2025-04-14 17:38:21 +02:00
Armin SchrenkandGitHub db6cf5459e CI: Update and split up anti virus whitelisting flow (#3817) 2025-04-14 16:09:22 +02:00
Armin SchrenkandGitHub 1d8466a9e3 Feature: Decrypt encrypted file name (#3788)
Closes #2713
2025-04-10 17:44:55 +02:00
Armin Schrenk dcbcd692e7 [skip ci] Merge branch 'main' into develop 2025-04-09 14:02:14 +02:00
Armin Schrenk 87fd6c712a Merge branch 'hotfix/1.15.3' 2025-04-09 13:59:50 +02:00
Armin Schrenk 958505559f finalize 1.15.3 2025-04-09 13:54:50 +02:00
Armin Schrenk 4736e5e7e7 prepare 1.15.3 2025-04-09 13:53:07 +02:00
Armin Schrenk 55d217887a fixes #3809 2025-04-09 11:04:20 +02:00
dependabot[bot]andGitHub 34ccd3ff73 Bump the maven-build-plugins group across 1 directory with 4 updates (#3813) 2025-04-08 15:49:18 +00:00
Tobias Hagemann 989c349331 Merge tag '1.15.2' into develop
# -----BEGIN SSH SIGNATURE-----
# U1NIU0lHAAAAAQAAAhcAAAAHc3NoLXJzYQAAAAMBAAEAAAIBAKgu9N6lXOixsGNEmzxZhA
# Rc8ABi3MlOHGT30s3zCQEtvbE/j1QXRycgru5n/TZPKiEqZz5OGLM7FG3lNqHTjrQG1jfZ
# rH9JfmTRX9kLWyDmsiKJkB0L19NcCJQKwhkAdcJkbhQHP4bk1o3uMS+M89n6Y0nmUocGrk
# j7yX/79iQn7PQXdDRk7I+p0p1hCMC7fRlhxPwBX8iPOoty9L75ZoteRoWMGoq4T2fhDdUd
# 5ASRKfdVDjUnFrYvI+o8mhXdbzxNLjp5oN9VWQsb+YIkzApcI1+42BT5WABk+3cLlheqPR
# SocNgYdoZZPA1x6Zlzy2gggm33m/uU7gww2iATphdoyXoj1Nv9loMDOaCQUe6s7Fnnn+xH
# hC1fJoCRlrWJ2QjQmZj18KkrXp2/ZNfvLYUIoQVONF40iizb5GJewH00m1ZV+/oAqbJ/W1
# nfLmXJ/ShwACe3hyZFVOaB2582UyTDFCFJL2Bgbiw8y1ayS15+gs9TkFJlAtbpwofPqVB2
# 16iiE8ViFf//J5ommM1S2sHXaPvu1D038OScIGnz0grhnCjzBr3BduW7EYQ6RhVOqMaEUy
# mQiRKIAtfj+6eHgk3IxB3ynReUFQqE3wreE9buA0vrCO4aWEet+qJsg+395K+/l7E6LQOg
# 5rkgcVj9rtFeo4gFBT2AUUSLmHaqpfABAAAAA2dpdAAAAAAAAAAGc2hhNTEyAAACFAAAAA
# xyc2Etc2hhMi0yNTYAAAIAMAXINugL3MrR1dUYQILEttmSOilND0hlz90eGBXuKRcijebq
# TbIwOrTJBPBlHM5aJC1lzBPcfB5Irz0DWc8eg0u2W/vHxtDXP5VL6me6u92Rz6WV73VWMD
# P8otZlMci0n3C5mM8DhrI9Nvg3qthRS2JW5vt3TFA7rL6IiAqsbA/nXWNGZuQwP+tJGCXg
# lWMD9NHaE1mmCcH+im2Vvnhz0y2Q0IEJCN8MDTrOA3ydnmF+YJ1b2QyQFBGrX3TNitZajX
# Uft3Jw5glpSlcaNEZOPR0cMCPBYy0skMUs4ykq4bVTy3I2qASdY3vb4l795OJPrK5FYyed
# ML5Zad7V8yrif0Cy/Ywy1C4TN6ftoEVH6HFEmJTohEY5BjT5qNK5tpmEs/o7z8W2oJa9Su
# G+KMAGe6AS/4ryQ+OQRJXzzFnAQRnR2Ou3iAA2ypsGWmP09Sr+1bb2qRSvy+lybaayfSLQ
# FouTQxecNq5TVfo1PWaGH9lLxd4i3J0PLk6uM8HfkIFimEN8h+4XT/4YXwO1czwun+IWaS
# nD92KIrdoHth+v05f8PpuqCz6odzojO33GfkMU/6Lkp2RgYeHD4eDb2/vyIJUtZHTPwPPJ
# tDybf2GbcDD4F43+fZdz7Q5A4a9DSDHeB6qZoqou6pUttbTneKQn/tq2yVa0TpyUjbGoCA
# QBvT4=
# -----END SSH SIGNATURE-----
# gpg verification failed.

# Conflicts:
#	pom.xml
2025-04-04 18:26:20 +02:00
Tobias Hagemann b9df56a6de Merge branch 'hotfix/1.15.2' 2025-04-04 18:24:13 +02:00
Tobias Hagemann 38dbefff0b Updated webdav-nio-adapter dependency, fixes #3806, fixes #3807 2025-04-04 18:12:03 +02:00
Tobias Hagemann 4cbe45919b Moved jfuse dependency bump into dependencyManagement 2025-04-04 17:43:44 +02:00
Armin Schrenk b7ccf7986d set version infos 2025-04-04 17:05:49 +02:00
Armin Schrenk 40d632a489 Closes #3807 2025-04-04 16:28:08 +02:00
Armin Schrenk 800aca5207 fix password enter dialog 2025-04-04 16:26:36 +02:00
Armin SchrenkandGitHub 6a26d95c15 Feature: Event view (#3780) 2025-04-03 18:10:22 +02:00
Tobias HagemannandGitHub 439d3d7529 Update CONTRIBUTING.md 2025-03-29 18:00:22 +01:00
Armin Schrenk 7476e192a3 [skip ci] fix wrong JDK version in appimage build 2025-03-24 17:16:46 +01:00
Armin Schrenk c6193bc259 update JDK for release builds to 23.0.2 (except ppa-builds) 2025-03-24 16:55:45 +01:00
Armin Schrenk 7446c69cd8 Update org.cryptomator:fuse-nio-adapter from 5.0.3 to 5.0.4
fixes #3797
2025-03-24 14:38:12 +01:00
133 changed files with 3638 additions and 1133 deletions
+4
View File
@@ -16,6 +16,10 @@
- Suggest your change by [submitting a new issue](https://github.com/cryptomator/cryptomator/issues/new/choose) and start writing code. - Suggest your change by [submitting a new issue](https://github.com/cryptomator/cryptomator/issues/new/choose) and start writing code.
## Do you intend to add a new translation or change an existing one?
Translations are not managed directly in this repository. Instead, we use [Crowdin](https://translate.cryptomator.org/), which automatically synchronizes translations with this repository. If you want to help us with translations, please visit our translation project on Crowdin.
## Code of Conduct ## Code of Conduct
Help us keep Cryptomator open and inclusive. Please read and follow our [Code of Conduct](https://github.com/cryptomator/cryptomator/blob/develop/.github/CODE_OF_CONDUCT.md). Help us keep Cryptomator open and inclusive. Please read and follow our [Code of Conduct](https://github.com/cryptomator/cryptomator/blob/develop/.github/CODE_OF_CONDUCT.md).
+25 -9
View File
@@ -8,16 +8,24 @@ on:
version: version:
description: 'Version' description: 'Version'
required: false required: false
push:
branches-ignore:
- 'dependabot/**'
paths:
- '.github/workflows/appimage.yml'
- 'dist/linux/appimage/**'
- 'dist/linux/common/**'
- 'dist/linux/resources/**'
env: env:
JAVA_DIST: 'temurin' JAVA_DIST: 'temurin'
JAVA_VERSION: '23.0.1+11' JAVA_VERSION: '24.0.1+9'
jobs: jobs:
get-version: get-version:
uses: ./.github/workflows/get-version.yml uses: ./.github/workflows/get-version.yml
with: with:
version: ${{ inputs.version }} version: ${{ inputs.version }} #okay if not defined
build: build:
name: Build AppImage name: Build AppImage
@@ -29,12 +37,12 @@ jobs:
include: include:
- os: ubuntu-latest - os: ubuntu-latest
appimage-suffix: x86_64 appimage-suffix: x86_64
openjfx-url: 'https://download2.gluonhq.com/openjfx/23.0.1/openjfx-23.0.1_linux-x64_bin-jmods.zip' openjfx-url: 'https://download2.gluonhq.com/openjfx/24.0.1/openjfx-24.0.1_linux-x64_bin-jmods.zip'
openjfx-sha: '2164bca470bf70a5e2764645e2078ba7f787b274e5be3d7df30d87c5bb62bba6' openjfx-sha: '425fac742b9fbd095b2ce868cff82d1024620f747c94a7144d0a4879e756146c'
- os: ubuntu-24.04-arm - os: ubuntu-24.04-arm
appimage-suffix: aarch64 appimage-suffix: aarch64
openjfx-url: 'https://download2.gluonhq.com/openjfx/23.0.1/openjfx-23.0.1_linux-aarch64_bin-jmods.zip' openjfx-url: 'https://download2.gluonhq.com/openjfx/24.0.1/openjfx-24.0.1_linux-aarch64_bin-jmods.zip'
openjfx-sha: '09c92fa9fa0b82adefd88640a14ebb2a49e5f3f733a57d1542f5590d060ffe1b' openjfx-sha: '7e02edd0f4ee5527a27c94b0bbba66fcaaff41009119e45d0eca0f96ddfb6e7b'
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Setup Java - name: Setup Java
@@ -61,7 +69,7 @@ jobs:
POM_JFX_VERSION=${POM_JFX_VERSION#*@} POM_JFX_VERSION=${POM_JFX_VERSION#*@}
POM_JFX_VERSION=${POM_JFX_VERSION%%.*} POM_JFX_VERSION=${POM_JFX_VERSION%%.*}
if [ $POM_JFX_VERSION -ne $JMOD_VERSION_AMD64 ]; then if [ $POM_JFX_VERSION -ne $JMOD_VERSION ]; then
>&2 echo "Major JavaFX version in pom.xml (${POM_JFX_VERSION}) != amd64 jmod version (${JMOD_VERSION})" >&2 echo "Major JavaFX version in pom.xml (${POM_JFX_VERSION}) != amd64 jmod version (${JMOD_VERSION})"
exit 1 exit 1
fi fi
@@ -73,13 +81,21 @@ jobs:
run: | run: |
cp LICENSE.txt target cp LICENSE.txt target
cp target/cryptomator-*.jar target/mods cp target/cryptomator-*.jar target/mods
- name: Run jlink with help option
id: jep-493-check
run: |
JMOD_PATHS="openjfx-jmods"
if ! ${JAVA_HOME}/bin/jlink --help | grep -q "Linking from run-time image enabled"; then
JMOD_PATHS="${JAVA_HOME}/jmods:${JMOD_PATHS}"
fi
echo "jmod_paths=${JMOD_PATHS}" >> "$GITHUB_OUTPUT"
- name: Run jlink - name: Run jlink
#Remark: no compression is applied for improved build compression later (here appimage) #Remark: no compression is applied for improved build compression later (here appimage)
run: > run: >
${JAVA_HOME}/bin/jlink ${JAVA_HOME}/bin/jlink
--verbose --verbose
--output runtime --output runtime
--module-path "${JAVA_HOME}/jmods:openjfx-jmods" --module-path "${{ steps.jep-493-check.outputs.jmod_paths }}"
--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.security.auth,jdk.accessibility,jdk.management.jfr,jdk.net,java.compiler --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.security.auth,jdk.accessibility,jdk.management.jfr,jdk.net,java.compiler
--strip-native-commands --strip-native-commands
--no-header-files --no-header-files
@@ -101,7 +117,7 @@ jobs:
--copyright "(C) 2016 - 2025 Skymatic GmbH" --copyright "(C) 2016 - 2025 Skymatic GmbH"
--app-version "${{ needs.get-version.outputs.semVerNum }}.${{ needs.get-version.outputs.revNum }}" --app-version "${{ needs.get-version.outputs.semVerNum }}.${{ needs.get-version.outputs.revNum }}"
--java-options "--enable-preview" --java-options "--enable-preview"
--java-options "--enable-native-access=org.cryptomator.jfuse.linux.amd64,org.cryptomator.jfuse.linux.aarch64,org.purejava.appindicator" --java-options "--enable-native-access=javafx.graphics,org.cryptomator.jfuse.linux.amd64,org.cryptomator.jfuse.linux.aarch64,org.purejava.appindicator"
--java-options "-Xss5m" --java-options "-Xss5m"
--java-options "-Xmx256m" --java-options "-Xmx256m"
--java-options "-Dcryptomator.appVersion=\"${{ needs.get-version.outputs.semVerStr }}\"" --java-options "-Dcryptomator.appVersion=\"${{ needs.get-version.outputs.semVerStr }}\""
+57 -9
View File
@@ -13,15 +13,48 @@ on:
description: "Url to the file to upload" description: "Url to the file to upload"
required: true required: true
type: string type: string
avast:
description: "Upload to Avast"
required: false
type: boolean
default: false
kaspersky:
description: "Upload to Kaspersky"
required: false
type: boolean
default: false
jobs: jobs:
allowlist: download-file:
name: Anti Virus Allowlisting name: Downloads the file into the VM
runs-on: ubuntu-latest runs-on: ubuntu-latest
outputs:
fileName: ${{ steps.extractName.outputs.fileName}}
steps: steps:
- name: Download file - name: Extract file name
id: extractName
run: | run: |
curl --remote-name ${{ inputs.url }} -L url="${{ inputs.url }}"
echo "fileName=${url##*/}" >> $GITHUB_OUTPUT
- name: Download file
run: curl --remote-name ${{ inputs.url }} -L -o ${{steps.extractName.outputs.fileName}}
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: ${{ steps.extractName.outputs.fileName }}
path: ${{ steps.extractName.outputs.fileName }}
if-no-files-found: error
allowlist-kaspersky:
name: Anti Virus Allowlisting Kaspersky
runs-on: ubuntu-latest
needs: download-file
if: github.event_name == 'workflow_call' || inputs.kaspersky
steps:
- name: Download artifact
uses: actions/download-artifact@v4
with:
name: ${{ needs.download-file.outputs.fileName }}
path: upload
- name: Upload to Kaspersky - name: Upload to Kaspersky
uses: SamKirkland/FTP-Deploy-Action@v4.3.5 uses: SamKirkland/FTP-Deploy-Action@v4.3.5
with: with:
@@ -30,11 +63,26 @@ jobs:
port: 990 port: 990
username: ${{ secrets.ALLOWLIST_KASPERSKY_USERNAME }} username: ${{ secrets.ALLOWLIST_KASPERSKY_USERNAME }}
password: ${{ secrets.ALLOWLIST_KASPERSKY_PASSWORD }} password: ${{ secrets.ALLOWLIST_KASPERSKY_PASSWORD }}
- name: Upload to Avast local-dir: ./upload/
uses: SamKirkland/FTP-Deploy-Action@v4.3.5 allowlist-avast:
name: Anti Virus Allowlisting Avast
runs-on: ubuntu-latest
needs: download-file
if: github.event_name == 'workflow_call' || inputs.avast
steps:
- name: Download artifact
uses: actions/download-artifact@v4
with:
name: ${{ needs.download-file.outputs.fileName }}
path: upload
- name: Upload to Avast
uses: wlixcc/SFTP-Deploy-Action@v1.2.5
with: with:
protocol: ftp
server: whitelisting.avast.com server: whitelisting.avast.com
port: 21 port: 22
username: ${{ secrets.ALLOWLIST_AVAST_USERNAME }} username: ${{ secrets.ALLOWLIST_AVAST_USERNAME }}
password: ${{ secrets.ALLOWLIST_AVAST_PASSWORD }} password: ${{ secrets.ALLOWLIST_AVAST_PASSWORD }}
ssh_private_key: ''
sftp_only: true
local_path: './upload/*'
remote_path: '/data'
+5 -1
View File
@@ -2,12 +2,16 @@ name: Build
on: on:
push: push:
paths:
- '.github/workflows/build.yml'
- 'pom.xml'
- 'src/**'
pull_request_target: pull_request_target:
types: [labeled] types: [labeled]
env: env:
JAVA_DIST: 'temurin' JAVA_DIST: 'temurin'
JAVA_VERSION: 23 JAVA_VERSION: 24
defaults: defaults:
run: run:
+1 -1
View File
@@ -6,7 +6,7 @@ on:
workflow_dispatch: workflow_dispatch:
env: env:
JDK_VERSION: '23.0.1+11' JDK_VERSION: '24.0.1+9'
JDK_VENDOR: temurin JDK_VENDOR: temurin
RUNTIME_VERSION_HELPER: > RUNTIME_VERSION_HELPER: >
public class Test { public class Test {
+37 -25
View File
@@ -5,41 +5,52 @@ on:
inputs: inputs:
semver: semver:
description: 'SemVer String (e.g. 1.7.0-beta1)' description: 'SemVer String (e.g. 1.7.0-beta1)'
required: true
ppaver: ppaver:
description: 'Base PPA Version String (e.g. 1.6.16+1.7.0~beta1) without -0ppa1' description: 'Base PPA Version String (e.g. 1.6.16+1.7.0~beta1) without -0ppa1'
required: true
dput: dput:
description: 'Upload to PPA' description: 'Upload to PPA'
required: true required: true
default: false default: false
type: boolean type: boolean
push:
branches-ignore:
- 'dependabot/**'
paths:
- '.github/workflows/debian.yml'
- 'dist/linux/debian/**'
- 'dist/linux/common/**'
- 'dist/linux/resources/**'
env: env:
JAVA_DIST: 'temurin' JAVA_DIST: 'temurin'
JAVA_VERSION: '23.0.1+11' JAVA_VERSION: '24.0.1+9'
COFFEELIBS_JDK: 23 COFFEELIBS_JDK: 24
COFFEELIBS_JDK_VERSION: '23.0.1+11-0ppa1' COFFEELIBS_JDK_VERSION: '24.0.1+9-0ppa3'
OPENJFX_JMODS_AMD64: 'https://download2.gluonhq.com/openjfx/23.0.1/openjfx-23.0.1_linux-x64_bin-jmods.zip' OPENJFX_JMODS_AMD64: 'https://download2.gluonhq.com/openjfx/24.0.1/openjfx-24.0.1_linux-x64_bin-jmods.zip'
OPENJFX_JMODS_AMD64_HASH: '2164bca470bf70a5e2764645e2078ba7f787b274e5be3d7df30d87c5bb62bba6' OPENJFX_JMODS_AMD64_HASH: '425fac742b9fbd095b2ce868cff82d1024620f747c94a7144d0a4879e756146c'
OPENJFX_JMODS_AARCH64: 'https://download2.gluonhq.com/openjfx/23.0.1/openjfx-23.0.1_linux-aarch64_bin-jmods.zip' OPENJFX_JMODS_AARCH64: 'https://download2.gluonhq.com/openjfx/24.0.1/openjfx-24.0.1_linux-aarch64_bin-jmods.zip'
OPENJFX_JMODS_AARCH64_HASH: '09c92fa9fa0b82adefd88640a14ebb2a49e5f3f733a57d1542f5590d060ffe1b' OPENJFX_JMODS_AARCH64_HASH: '7e02edd0f4ee5527a27c94b0bbba66fcaaff41009119e45d0eca0f96ddfb6e7b'
jobs: jobs:
get-version:
uses: ./.github/workflows/get-version.yml
with:
version: ${{ inputs.semver }} #okay if not defined
build: build:
name: Build Debian Package name: Build Debian Package
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
needs: [get-version]
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- id: versions - id: deb-version
name: Get version information name: Determine deb-version
run: | run: |
SEM_VER_STR="${{ inputs.semver }}" if [ -n "${{inputs.ppaver}}" ]; then
SEM_VER_NUM=`echo ${SEM_VER_STR} | sed -E 's/([0-9]+\.[0-9]+\.[0-9]+).*/\1/'` echo "debVersion=${{inputs.ppaver }}" >> "$GITHUB_OUTPUT"
REVCOUNT=`git rev-list --count HEAD` else
echo "semVerStr=${SEM_VER_STR}" >> $GITHUB_OUTPUT echo "debVersion=${{needs.get-version.outputs.semVerStr}}" >> "$GITHUB_OUTPUT"
echo "semVerNum=${SEM_VER_NUM}" >> $GITHUB_OUTPUT fi
echo "revNum=${REVCOUNT}" >> $GITHUB_OUTPUT
- name: Install build tools - name: Install build tools
run: | run: |
sudo add-apt-repository ppa:coffeelibs/openjdk sudo add-apt-repository ppa:coffeelibs/openjdk
@@ -94,7 +105,7 @@ jobs:
cp -r jmods pkgdir cp -r jmods pkgdir
cp -r dist/linux/common/ pkgdir cp -r dist/linux/common/ pkgdir
cp target/cryptomator-*.jar pkgdir/mods cp target/cryptomator-*.jar pkgdir/mods
tar -cJf cryptomator_${{ inputs.ppaver }}.orig.tar.xz -C pkgdir . tar -cJf cryptomator_${{ steps.deb-version.outputs.debVersion }}.orig.tar.xz -C pkgdir .
- name: Patch and rename pkgdir - name: Patch and rename pkgdir
run: | run: |
cp -r dist/linux/debian/ pkgdir cp -r dist/linux/debian/ pkgdir
@@ -103,12 +114,12 @@ jobs:
envsubst '${SEMVER_STR} ${VERSION_NUM} ${REVISION_NUM} ${DISABLE_UPDATE_CHECK}' < dist/linux/debian/rules > pkgdir/debian/rules envsubst '${SEMVER_STR} ${VERSION_NUM} ${REVISION_NUM} ${DISABLE_UPDATE_CHECK}' < dist/linux/debian/rules > pkgdir/debian/rules
envsubst '${PPA_VERSION} ${RFC2822_TIMESTAMP}' < dist/linux/debian/changelog > pkgdir/debian/changelog envsubst '${PPA_VERSION} ${RFC2822_TIMESTAMP}' < dist/linux/debian/changelog > pkgdir/debian/changelog
find . -name "*.jar" >> pkgdir/debian/source/include-binaries find . -name "*.jar" >> pkgdir/debian/source/include-binaries
mv pkgdir cryptomator_${{ inputs.ppaver }} mv pkgdir cryptomator_${{ steps.deb-version.outputs.debVersion }}
env: env:
SEMVER_STR: ${{ steps.versions.outputs.semVerStr }} SEMVER_STR: ${{ needs.get-version.outputs.semVerStr }}
VERSION_NUM: ${{ steps.versions.outputs.semVerNum }} VERSION_NUM: ${{ needs.get-version.outputs.semVerNum }}
REVISION_NUM: ${{ steps.versions.outputs.revNum }} REVISION_NUM: ${{ needs.get-version.outputs.revNum }}
PPA_VERSION: ${{ inputs.ppaver }}-0ppa1 PPA_VERSION: ${{ steps.deb-version.outputs.debVersion }}-0ppa1
- name: Prepare GPG-Agent for signing with key 615D449FE6E6A235 - name: Prepare GPG-Agent for signing with key 615D449FE6E6A235
run: | run: |
echo "${GPG_PRIVATE_KEY}" | gpg --batch --quiet --import echo "${GPG_PRIVATE_KEY}" | gpg --batch --quiet --import
@@ -118,12 +129,13 @@ jobs:
GPG_PASSPHRASE: ${{ secrets.RELEASES_GPG_PASSPHRASE }} GPG_PASSPHRASE: ${{ secrets.RELEASES_GPG_PASSPHRASE }}
- name: debuild - name: debuild
run: | run: |
(sleep 8m; gpg --batch --quiet --pinentry-mode loopback -u 615D449FE6E6A235 --dry-run --sign README.md) &
debuild -S -sa -d debuild -S -sa -d
debuild -b -sa -d debuild -b -sa -d
env: env:
DEBSIGN_PROGRAM: gpg --batch --pinentry-mode loopback DEBSIGN_PROGRAM: gpg --batch --pinentry-mode loopback
DEBSIGN_KEYID: 615D449FE6E6A235 DEBSIGN_KEYID: 615D449FE6E6A235
working-directory: cryptomator_${{ inputs.ppaver }} working-directory: cryptomator_${{ steps.deb-version.outputs.debVersion }}
- name: Create detached GPG signatures - name: Create detached GPG signatures
run: | run: |
gpg --batch --quiet --passphrase-fd 0 --pinentry-mode loopback -u 615D449FE6E6A235 --detach-sign -a cryptomator_*_amd64.deb gpg --batch --quiet --passphrase-fd 0 --pinentry-mode loopback -u 615D449FE6E6A235 --detach-sign -a cryptomator_*_amd64.deb
@@ -140,7 +152,7 @@ jobs:
cryptomator_*_amd64.deb cryptomator_*_amd64.deb
cryptomator_*.asc cryptomator_*.asc
- name: Publish on PPA - name: Publish on PPA
if: inputs.dput if: inputs.dput && inputs.ppaver != ''
run: dput ppa:sebastian-stenzel/cryptomator-beta cryptomator_*_source.changes run: dput ppa:sebastian-stenzel/cryptomator-beta cryptomator_*_source.changes
# If ref is a tag, also upload to GitHub Releases: # If ref is a tag, also upload to GitHub Releases:
- name: Publish Debian package on GitHub Releases - name: Publish Debian package on GitHub Releases
+1 -1
View File
@@ -11,7 +11,7 @@ jobs:
with: with:
runner-os: 'ubuntu-latest' runner-os: 'ubuntu-latest'
java-distribution: 'temurin' java-distribution: 'temurin'
java-version: 23 java-version: 24
check-command: 'mvn -B validate -Pdependency-check -Djavafx.platform=linux' check-command: 'mvn -B validate -Pdependency-check -Djavafx.platform=linux'
secrets: secrets:
nvd-api-key: ${{ secrets.NVD_API_KEY }} nvd-api-key: ${{ secrets.NVD_API_KEY }}
+1 -1
View File
@@ -23,7 +23,7 @@ on:
env: env:
JAVA_DIST: 'temurin' JAVA_DIST: 'temurin'
JAVA_VERSION: 23 JAVA_VERSION: 24
jobs: jobs:
determine-version: determine-version:
+25 -8
View File
@@ -2,20 +2,29 @@ name: Build macOS .dmg for x64
####################################### #######################################
# STOP! DO NOT EDIT THIS FILE! # STOP! DO NOT EDIT THIS FILE!
# #
# It is a copy of mac-dmg.yml with tiny adjustements (mainly lines 42 to 47) # It is a copy of mac-dmg.yml with tiny adjustements (mainly lines 42 to 47)
# It was made necessary, since Github does not offer free macos intel runners for macos 15 and above. # It was made necessary, since Github does not offer free macos intel runners for macos 15 and above.
# This workflow can only be triggered by a release. #
#
####################################### #######################################
on: on:
release: release:
types: [published] types: [published]
workflow_dispatch:
inputs:
version:
description: 'Version'
required: false
notarize:
description: 'Notarize'
required: true
default: false
type: boolean
env: env:
JAVA_DIST: 'temurin' JAVA_DIST: 'temurin'
JAVA_VERSION: '23.0.1+11' JAVA_VERSION: '24.0.1+9'
jobs: jobs:
get-version: get-version:
@@ -35,8 +44,8 @@ jobs:
architecture: x64 architecture: x64
output-suffix: x64 output-suffix: x64
fuse-lib: macFUSE fuse-lib: macFUSE
openjfx-url: 'https://download2.gluonhq.com/openjfx/23.0.1/openjfx-23.0.1_osx-x64_bin-jmods.zip' openjfx-url: 'https://download2.gluonhq.com/openjfx/24.0.1/openjfx-24.0.1_osx-x64_bin-jmods.zip'
openjfx-sha: '8857965975c464a0e5d57709292ce357d0ebb39f6168c41d5ca38301e42c3c8e' openjfx-sha: '6e62a426d43c168a488521f904a523f3dd6ee2cf103e08136f2fd465c828a105'
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Setup Java - name: Setup Java
@@ -75,13 +84,21 @@ jobs:
run: | run: |
cp LICENSE.txt target cp LICENSE.txt target
cp target/cryptomator-*.jar target/mods cp target/cryptomator-*.jar target/mods
- name: Run jlink with help option
id: jep-493-check
run: |
JMOD_PATHS="openjfx-jmods"
if ! ${JAVA_HOME}/bin/jlink --help | grep -q "Linking from run-time image enabled"; then
JMOD_PATHS="${JAVA_HOME}/jmods:${JMOD_PATHS}"
fi
echo "jmod_paths=${JMOD_PATHS}" >> "$GITHUB_OUTPUT"
- name: Run jlink - name: Run jlink
#Remark: no compression is applied for improved build compression later (here dmg) #Remark: no compression is applied for improved build compression later (here dmg)
run: > run: >
${JAVA_HOME}/bin/jlink ${JAVA_HOME}/bin/jlink
--verbose --verbose
--output runtime --output runtime
--module-path "${JAVA_HOME}/jmods:openjfx-jmods" --module-path "${{ steps.jep-493-check.outputs.jmod_paths }}"
--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.accessibility,jdk.management.jfr,java.compiler --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.accessibility,jdk.management.jfr,java.compiler
--strip-native-commands --strip-native-commands
--no-header-files --no-header-files
@@ -103,7 +120,7 @@ jobs:
--copyright "(C) 2016 - 2025 Skymatic GmbH" --copyright "(C) 2016 - 2025 Skymatic GmbH"
--app-version "${{ needs.get-version.outputs.semVerNum }}" --app-version "${{ needs.get-version.outputs.semVerNum }}"
--java-options "--enable-preview" --java-options "--enable-preview"
--java-options "--enable-native-access=org.cryptomator.jfuse.mac" --java-options "--enable-native-access=javafx.graphics,org.cryptomator.jfuse.mac"
--java-options "-Xss5m" --java-options "-Xss5m"
--java-options "-Xmx256m" --java-options "-Xmx256m"
--java-options "-Dfile.encoding=\"utf-8\"" --java-options "-Dfile.encoding=\"utf-8\""
+19 -5
View File
@@ -13,10 +13,16 @@ on:
required: true required: true
default: false default: false
type: boolean type: boolean
push:
branches-ignore:
- 'dependabot/**'
paths:
- '.github/workflows/mac-dmg.yml'
- 'dist/mac/**'
env: env:
JAVA_DIST: 'temurin' JAVA_DIST: 'temurin'
JAVA_VERSION: '23.0.1+11' JAVA_VERSION: '24.0.1+9'
jobs: jobs:
get-version: get-version:
@@ -36,8 +42,8 @@ jobs:
architecture: aarch64 architecture: aarch64
output-suffix: arm64 output-suffix: arm64
fuse-lib: FUSE-T fuse-lib: FUSE-T
openjfx-url: 'https://download2.gluonhq.com/openjfx/23.0.1/openjfx-23.0.1_osx-aarch64_bin-jmods.zip' openjfx-url: 'https://download2.gluonhq.com/openjfx/24.0.1/openjfx-24.0.1_osx-aarch64_bin-jmods.zip'
openjfx-sha: 'a800724a1f3e6757ecfa0bd5bf7ed64d2e6a7a3f5b3522650a70b8cfc7782fb6' openjfx-sha: 'b5a94a13077507003fa852512bfa33f4fb680bc8076d8002e4227a84c85171d4'
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Setup Java - name: Setup Java
@@ -76,13 +82,21 @@ jobs:
run: | run: |
cp LICENSE.txt target cp LICENSE.txt target
cp target/cryptomator-*.jar target/mods cp target/cryptomator-*.jar target/mods
- name: Run jlink with help option
id: jep-493-check
run: |
JMOD_PATHS="openjfx-jmods"
if ! ${JAVA_HOME}/bin/jlink --help | grep -q "Linking from run-time image enabled"; then
JMOD_PATHS="${JAVA_HOME}/jmods:${JMOD_PATHS}"
fi
echo "jmod_paths=${JMOD_PATHS}" >> "$GITHUB_OUTPUT"
- name: Run jlink - name: Run jlink
#Remark: no compression is applied for improved build compression later (here dmg) #Remark: no compression is applied for improved build compression later (here dmg)
run: > run: >
${JAVA_HOME}/bin/jlink ${JAVA_HOME}/bin/jlink
--verbose --verbose
--output runtime --output runtime
--module-path "${JAVA_HOME}/jmods:openjfx-jmods" --module-path "${{ steps.jep-493-check.outputs.jmod_paths }}"
--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.accessibility,jdk.management.jfr,java.compiler --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.accessibility,jdk.management.jfr,java.compiler
--strip-native-commands --strip-native-commands
--no-header-files --no-header-files
@@ -104,7 +118,7 @@ jobs:
--copyright "(C) 2016 - 2025 Skymatic GmbH" --copyright "(C) 2016 - 2025 Skymatic GmbH"
--app-version "${{ needs.get-version.outputs.semVerNum }}" --app-version "${{ needs.get-version.outputs.semVerNum }}"
--java-options "--enable-preview" --java-options "--enable-preview"
--java-options "--enable-native-access=org.cryptomator.jfuse.mac" --java-options "--enable-native-access=javafx.graphics,org.cryptomator.jfuse.mac"
--java-options "-Xss5m" --java-options "-Xss5m"
--java-options "-Xmx256m" --java-options "-Xmx256m"
--java-options "-Dfile.encoding=\"utf-8\"" --java-options "-Dfile.encoding=\"utf-8\""
+1 -2
View File
@@ -5,7 +5,7 @@ on:
env: env:
JAVA_DIST: 'temurin' JAVA_DIST: 'temurin'
JAVA_VERSION: 23 JAVA_VERSION: 24
defaults: defaults:
run: run:
@@ -15,7 +15,6 @@ jobs:
test: test:
name: Compile and Test name: Compile and Test
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: "!contains(github.event.head_commit.message, '[ci skip]') && !contains(github.event.head_commit.message, '[skip ci]')"
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: actions/setup-java@v4 - uses: actions/setup-java@v4
+130 -68
View File
@@ -12,13 +12,17 @@ on:
description: 'Build debug version with console output' description: 'Build debug version with console output'
type: boolean type: boolean
default: false default: false
push:
branches-ignore:
- 'dependabot/**'
paths:
- '.github/workflows/win-exe.yml'
- 'dist/win/**'
env: env:
JAVA_DIST: 'zulu' OPENJFX_JMODS_AMD64: 'https://download2.gluonhq.com/openjfx/24.0.1/openjfx-24.0.1_windows-x64_bin-jmods.zip'
JAVA_VERSION: '23.0.1+11' OPENJFX_JMODS_AMD64_HASH: 'f13d17c7caf88654fc835f1b4e75a9b0f34a888eb8abef381796c0002e63b03f'
OPENJFX_JMODS_AMD64: 'https://download2.gluonhq.com/openjfx/23.0.1/openjfx-23.0.1_windows-x64_bin-jmods.zip'
OPENJFX_JMODS_AMD64_HASH: 'ee176dcee3bd78bde7910735bd67f67c792882f5b89626796ae06f7a1c0119d3'
WINFSP_MSI: 'https://github.com/winfsp/winfsp/releases/download/v2.0/winfsp-2.0.23075.msi' WINFSP_MSI: 'https://github.com/winfsp/winfsp/releases/download/v2.0/winfsp-2.0.23075.msi'
WINFSP_UNINSTALLER: 'https://github.com/cryptomator/winfsp-uninstaller/releases/latest/download/winfsp-uninstaller.exe' WINFSP_UNINSTALLER: 'https://github.com/cryptomator/winfsp-uninstaller/releases/latest/download/winfsp-uninstaller.exe'
@@ -34,36 +38,54 @@ jobs:
build-msi: build-msi:
name: Build .msi Installer name: Build .msi Installer
runs-on: windows-latest runs-on: ${{ matrix.os }}
needs: [get-version] needs: [ get-version ]
strategy:
matrix:
include:
- arch: x64
os: windows-latest
java-dist: 'zulu'
java-version: '24.0.1+9'
java-package: 'jdk'
- arch: arm64
os: windows-11-arm
java-dist: 'liberica'
java-version: '24.0.1+11'
java-package: 'jdk+fx' #This is needed, as liberica contains JFX 24 Jmods for Windows ARM64
env: env:
LOOPBACK_ALIAS: 'cryptomator-vault' LOOPBACK_ALIAS: 'cryptomator-vault'
WIN_CONSOLE_FLAG: '' WIN_CONSOLE_FLAG: ''
steps: steps:
- name: Upgrade WIX to latest version
run: choco install wixtoolset --version 3.14.1
shell: pwsh
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Setup Java - name: Setup Java
uses: actions/setup-java@v4 uses: actions/setup-java@v4
with: with:
distribution: ${{ env.JAVA_DIST }} distribution: ${{ matrix.java-dist }}
java-version: ${{ env.JAVA_VERSION }} java-version: ${{ matrix.java-version }}
java-package: ${{ matrix.java-package }}
check-latest: true check-latest: true
cache: 'maven' cache: 'maven'
- name: Install wix and extensions
run: |
dotnet tool install --global wix --version 6.0.0
wix.exe extension add WixToolset.UI.wixext/6.0.0 --global
wix.exe extension add WixToolset.Util.wixext/6.0.0 --global
- name: Download and extract JavaFX jmods from Gluon - name: Download and extract JavaFX jmods from Gluon
if: matrix.arch == 'x64'
#In the last step we move all jmods files a dir level up because jmods are placed inside a directory in the zip #In the last step we move all jmods files a dir level up because jmods are placed inside a directory in the zip
run: | run: |
curl --output jfxjmods.zip -L "${{ env.OPENJFX_JMODS_AMD64 }}" curl --output openjfx-jmods.zip -L "${{ env.OPENJFX_JMODS_AMD64 }}"
if(!(Get-FileHash -Path jfxjmods.zip -Algorithm SHA256).Hash.ToLower().equals("${{ env.OPENJFX_JMODS_AMD64_HASH }}")) { if(!(Get-FileHash -Path openjfx-jmods.zip -Algorithm SHA256).Hash.ToLower().equals("${{ env.OPENJFX_JMODS_AMD64_HASH }}")) {
throw "Wrong checksum of JMOD archive downloaded from ${{ env.OPENJFX_JMODS_AMD64 }}."; throw "Wrong checksum of JMOD archive downloaded from ${{ env.OPENJFX_JMODS_AMD64 }}.";
} }
Expand-Archive -Path jfxjmods.zip -DestinationPath jfxjmods Expand-Archive -Path openjfx-jmods.zip -DestinationPath openjfx-jmods
Get-ChildItem -Path jfxjmods -Recurse -Filter "*.jmod" | ForEach-Object { Move-Item -Path $_ -Destination $_.Directory.Parent} Get-ChildItem -Path openjfx-jmods -Recurse -Filter "*.jmod" | ForEach-Object { Move-Item -Path $_ -Destination $_.Directory.Parent}
shell: pwsh shell: pwsh
- name: Ensure major jfx version in pom and in jmods is the same - name: Ensure major jfx version in pom and in jmods is the same
if: matrix.arch == 'x64'
run: | run: |
JMOD_VERSION_AMD64=$(jmod describe jfxjmods/javafx.base.jmod | head -1) JMOD_VERSION_AMD64=$(jmod describe openjfx-jmods/javafx.base.jmod | head -1)
JMOD_VERSION_AMD64=${JMOD_VERSION_AMD64#*@} JMOD_VERSION_AMD64=${JMOD_VERSION_AMD64#*@}
JMOD_VERSION_AMD64=${JMOD_VERSION_AMD64%%.*} JMOD_VERSION_AMD64=${JMOD_VERSION_AMD64%%.*}
POM_JFX_VERSION=$(mvn help:evaluate "-Dexpression=javafx.version" -q -DforceStdout) POM_JFX_VERSION=$(mvn help:evaluate "-Dexpression=javafx.version" -q -DforceStdout)
@@ -75,20 +97,28 @@ jobs:
exit 1 exit 1
fi fi
- name: Set version - name: Set version
run : mvn versions:set -DnewVersion=${{ needs.get-version.outputs.semVerStr }} run: mvn versions:set -DnewVersion=${{ needs.get-version.outputs.semVerStr }}
- name: Run maven - name: Run maven
run: mvn -B clean package -Pwin -DskipTests -Djavafx.platform=win run: mvn -B clean package -Pwin -DskipTests -Djavafx.platform=win
- name: Patch target dir - name: Patch target dir
run: | run: |
cp LICENSE.txt target cp LICENSE.txt target
cp target/cryptomator-*.jar target/mods cp target/cryptomator-*.jar target/mods
- name: Run jlink with help option
id: jep-493-check
run: |
JMOD_PATHS="openjfx-jmods"
if ! $(${JAVA_HOME}/bin/jlink --help | grep -q "Linking from run-time image enabled"); then
JMOD_PATHS="${JAVA_HOME}/jmods;${JMOD_PATHS}"
fi
echo "jmod_paths=${JMOD_PATHS}" >> "$GITHUB_OUTPUT"
- name: Run jlink - name: Run jlink
#Remark: no compression is applied for improved build compression later (here msi) # Remark: no compression is applied for improved build compression later (here msi)
run: > run: >
${JAVA_HOME}/bin/jlink ${JAVA_HOME}/bin/jlink
--verbose --verbose
--output runtime --output runtime
--module-path "jfxjmods;${JAVA_HOME}/jmods" --module-path "${{ steps.jep-493-check.outputs.jmod_paths }}"
--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.crypto.mscapi,jdk.unsupported,jdk.accessibility,jdk.management.jfr,java.compiler --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.crypto.mscapi,jdk.unsupported,jdk.accessibility,jdk.management.jfr,java.compiler
--strip-native-commands --strip-native-commands
--no-header-files --no-header-files
@@ -113,7 +143,7 @@ jobs:
--copyright "(C) 2016 - 2025 Skymatic GmbH" --copyright "(C) 2016 - 2025 Skymatic GmbH"
--app-version "${{ needs.get-version.outputs.semVerNum }}.${{ needs.get-version.outputs.revNum }}" --app-version "${{ needs.get-version.outputs.semVerNum }}.${{ needs.get-version.outputs.revNum }}"
--java-options "--enable-preview" --java-options "--enable-preview"
--java-options "--enable-native-access=org.cryptomator.jfuse.win,org.cryptomator.integrations.win" --java-options "--enable-native-access=javafx.graphics,org.cryptomator.jfuse.win,org.cryptomator.integrations.win"
--java-options "-Xss5m" --java-options "-Xss5m"
--java-options "-Xmx256m" --java-options "-Xmx256m"
--java-options "-Dcryptomator.appVersion=\"${{ needs.get-version.outputs.semVerStr }}\"" --java-options "-Dcryptomator.appVersion=\"${{ needs.get-version.outputs.semVerStr }}\""
@@ -130,6 +160,7 @@ jobs:
--java-options "-Dcryptomator.buildNumber=\"msi-${{ needs.get-version.outputs.revNum }}\"" --java-options "-Dcryptomator.buildNumber=\"msi-${{ needs.get-version.outputs.revNum }}\""
--java-options "-Dcryptomator.integrationsWin.autoStartShellLinkName=\"Cryptomator\"" --java-options "-Dcryptomator.integrationsWin.autoStartShellLinkName=\"Cryptomator\""
--java-options "-Dcryptomator.integrationsWin.keychainPaths=\"@{appdata}/Cryptomator/keychain.json;@{userhome}/AppData/Roaming/Cryptomator/keychain.json\"" --java-options "-Dcryptomator.integrationsWin.keychainPaths=\"@{appdata}/Cryptomator/keychain.json;@{userhome}/AppData/Roaming/Cryptomator/keychain.json\""
--java-options "-Dcryptomator.integrationsWin.windowsHelloKeychainPaths=\"@{appdata}/Cryptomator/windowsHelloKeychain.json\""
--java-options "-Djavafx.verbose=${{ inputs.isDebug }}" --java-options "-Djavafx.verbose=${{ inputs.isDebug }}"
--resource-dir dist/win/resources --resource-dir dist/win/resources
--icon dist/win/resources/Cryptomator.ico --icon dist/win/resources/Cryptomator.ico
@@ -240,8 +271,8 @@ jobs:
description: Cryptomator Installer description: Cryptomator Installer
timestampUrl: 'http://timestamp.digicert.com' timestampUrl: 'http://timestamp.digicert.com'
folder: installer folder: installer
- name: Add possible alpha/beta tags to installer name - name: Add possible alpha/beta tags and architecture to installer name
run: mv installer/Cryptomator-*.msi Cryptomator-${{ needs.get-version.outputs.semVerStr }}-x64.msi run: mv installer/Cryptomator-*.msi Cryptomator-${{ needs.get-version.outputs.semVerStr }}-${{ matrix.arch }}.msi
- name: Create detached GPG signature with key 615D449FE6E6A235 - name: Create detached GPG signature with key 615D449FE6E6A235
run: | run: |
echo "${GPG_PRIVATE_KEY}" | gpg --batch --quiet --import echo "${GPG_PRIVATE_KEY}" | gpg --batch --quiet --import
@@ -252,7 +283,7 @@ jobs:
- name: Upload artifacts - name: Upload artifacts
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: msi name: msi-${{ matrix.arch }}
path: | path: |
Cryptomator-*.msi Cryptomator-*.msi
Cryptomator-*.asc Cryptomator-*.asc
@@ -260,21 +291,43 @@ jobs:
build-exe: build-exe:
name: Build .exe installer name: Build .exe installer
runs-on: windows-latest runs-on: ${{ matrix.os }}
needs: [get-version, build-msi] needs: [ get-version, build-msi ]
strategy:
matrix:
include:
- arch: x64
os: windows-latest
executable-suffix: x64
java-dist: 'zulu'
java-version: '24.0.1+9'
java-package: 'jdk'
- arch: arm64
os: windows-11-arm
executable-suffix: arm64
java-dist: 'liberica'
java-version: '24.0.1+11'
java-package: 'jdk+fx' #This is needed, as liberica contains JFX 24 Jmods for Windows ARM64
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Install wix and extensions
run: |
dotnet tool install --global wix --version 6.0.0
wix.exe extension add WixToolset.BootstrapperApplications.wixext/6.0.0 --global
wix.exe extension add WixToolset.Util.wixext/6.0.0 --global
- name: Download .msi - name: Download .msi
uses: actions/download-artifact@v4 uses: actions/download-artifact@v4
with: with:
name: msi name: msi-${{ matrix.arch }}
path: dist/win/bundle/resources path: dist/win/bundle/resources
- name: Strip version info from msi file name - name: Strip version info from msi file name
run: mv dist/win/bundle/resources/Cryptomator*.msi dist/win/bundle/resources/Cryptomator.msi run: mv dist/win/bundle/resources/Cryptomator*.msi dist/win/bundle/resources/Cryptomator.msi
- uses: actions/setup-java@v4 - name: Setup Java
uses: actions/setup-java@v4
with: with:
distribution: ${{ env.JAVA_DIST }} distribution: ${{ matrix.java-dist }}
java-version: ${{ env.JAVA_VERSION }} java-version: ${{ matrix.java-version }}
java-package: ${{ matrix.java-package }}
check-latest: true check-latest: true
cache: 'maven' cache: 'maven'
- name: Generate license for exe - name: Generate license for exe
@@ -296,29 +349,24 @@ jobs:
run: | run: |
curl --output dist/win/bundle/resources/winfsp-uninstaller.exe -L ${{ env.WINFSP_UNINSTALLER }} curl --output dist/win/bundle/resources/winfsp-uninstaller.exe -L ${{ env.WINFSP_UNINSTALLER }}
shell: pwsh shell: pwsh
- name: Compile to wixObj file - name: Create Wix Burn bundle
working-directory: dist/win
run: > run: >
"${WIX}/bin/candle.exe" dist/win/bundle/bundleWithWinfsp.wxs wix build
-ext WixBalExtension -define BundleName="Cryptomator"
-ext WixUtilExtension -define BundleVersion="${{ needs.get-version.outputs.semVerNum }}.${{ needs.get-version.outputs.revNum}}"
-out dist/win/bundle/ -define BundleVendor="Skymatic GmbH"
-dBundleVersion="${{ needs.get-version.outputs.semVerNum }}.${{ needs.get-version.outputs.revNum }}" -define BundleCopyright="(C) 2016 - 2025 Skymatic GmbH"
-dBundleVendor="Skymatic GmbH" -define AboutUrl="https://cryptomator.org"
-dBundleCopyright="(C) 2016 - 2025 Skymatic GmbH" -define HelpUrl="https://cryptomator.org/contact"
-dAboutUrl="https://cryptomator.org" -define UpdateUrl="https://cryptomator.org/downloads/"
-dHelpUrl="https://cryptomator.org/contact" -ext "WixToolset.Util.wixext"
-dUpdateUrl="https://cryptomator.org/downloads/" -ext "WixToolset.BootstrapperApplications.wixext"
- name: Create executable with linker ./bundle/bundleWithWinfsp.wxs
run: > -out "../../installer/unsigned/Cryptomator-Installer.exe"
"${WIX}/bin/light.exe" -b dist/win/ dist/win/bundle/bundleWithWinfsp.wixobj
-ext WixBalExtension
-ext WixUtilExtension
-out installer/unsigned/Cryptomator-Installer.exe
- name: Detach burn engine in preparation to sign - name: Detach burn engine in preparation to sign
run: > run: >
"${WIX}/bin/insignia.exe" wix burn detach installer/unsigned/Cryptomator-Installer.exe -engine tmp/engine.exe
-ib installer/unsigned/Cryptomator-Installer.exe
-o tmp/engine.exe
- name: Codesign burn engine - name: Codesign burn engine
uses: skymatic/code-sign-action@v3 uses: skymatic/code-sign-action@v3
with: with:
@@ -329,10 +377,8 @@ jobs:
timestampUrl: 'http://timestamp.digicert.com' timestampUrl: 'http://timestamp.digicert.com'
folder: tmp folder: tmp
- name: Reattach signed burn engine to installer - name: Reattach signed burn engine to installer
run : > run: >
"${WIX}/bin/insignia.exe" wix burn reattach installer/unsigned/Cryptomator-Installer.exe -engine tmp/engine.exe -o installer/Cryptomator-Installer.exe
-ab tmp/engine.exe installer/unsigned/Cryptomator-Installer.exe
-o installer/Cryptomator-Installer.exe
- name: Codesign EXE - name: Codesign EXE
uses: skymatic/code-sign-action@v3 uses: skymatic/code-sign-action@v3
with: with:
@@ -343,7 +389,7 @@ jobs:
timestampUrl: 'http://timestamp.digicert.com' timestampUrl: 'http://timestamp.digicert.com'
folder: installer folder: installer
- name: Add possible alpha/beta tags to installer name - name: Add possible alpha/beta tags to installer name
run: mv installer/Cryptomator-Installer.exe Cryptomator-${{ needs.get-version.outputs.semVerStr }}-x64.exe run: mv installer/Cryptomator-Installer.exe Cryptomator-${{ needs.get-version.outputs.semVerStr }}-${{ matrix.executable-suffix }}.exe
- name: Create detached GPG signature with key 615D449FE6E6A235 - name: Create detached GPG signature with key 615D449FE6E6A235
run: | run: |
echo "${GPG_PRIVATE_KEY}" | gpg --batch --quiet --import echo "${GPG_PRIVATE_KEY}" | gpg --batch --quiet --import
@@ -354,7 +400,7 @@ jobs:
- name: Upload artifacts - name: Upload artifacts
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: exe name: exe-${{ matrix.executable-suffix }}
path: | path: |
Cryptomator-*.exe Cryptomator-*.exe
Cryptomator-*.asc Cryptomator-*.asc
@@ -364,16 +410,18 @@ jobs:
name: Publish installers to the github release name: Publish installers to the github release
if: startsWith(github.ref, 'refs/tags/') && github.event.action == 'published' if: startsWith(github.ref, 'refs/tags/') && github.event.action == 'published'
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: [build-msi, build-exe] needs: [ build-msi, build-exe ]
outputs: outputs:
download-url-msi: ${{ fromJSON(steps.publish.outputs.assets)[0].browser_download_url }} download-url-msi-x64: ${{ fromJSON(steps.publish.outputs.assets)[0].browser_download_url }}
download-url-exe: ${{ fromJSON(steps.publish.outputs.assets)[1].browser_download_url }} download-url-msi-arm64: ${{ fromJSON(steps.publish.outputs.assets)[1].browser_download_url }}
download-url-exe-x64: ${{ fromJSON(steps.publish.outputs.assets)[2].browser_download_url }}
download-url-exe-arm64: ${{ fromJSON(steps.publish.outputs.assets)[3].browser_download_url }}
steps: steps:
- name: Download installers - name: Download installers
uses: actions/download-artifact@v4 uses: actions/download-artifact@v4
with: with:
merge-multiple: true merge-multiple: true
- name: Publish .msi on GitHub Releases - name: Publish installers on GitHub Releases
id: publish id: publish
uses: softprops/action-gh-release@v2 uses: softprops/action-gh-release@v2
with: with:
@@ -385,18 +433,32 @@ jobs:
*.exe *.exe
*.asc *.asc
allowlist-msi: allowlist-msi-x64:
uses: ./.github/workflows/av-whitelist.yml uses: ./.github/workflows/av-whitelist.yml
needs: [publish] needs: [ publish ]
with: with:
url: ${{ needs.publish.outputs.download-url-msi }} url: ${{ needs.publish.outputs.download-url-msi-x64 }}
secrets: inherit secrets: inherit
allowlist-exe: allowlist-msi-arm64:
uses: ./.github/workflows/av-whitelist.yml uses: ./.github/workflows/av-whitelist.yml
needs: [publish] needs: [ publish ]
with: with:
url: ${{ needs.publish.outputs.download-url-exe }} url: ${{ needs.publish.outputs.download-url-msi-arm64 }}
secrets: inherit
allowlist-exe-x64:
uses: ./.github/workflows/av-whitelist.yml
needs: [ publish, allowlist-msi-x64 ]
with:
url: ${{ needs.publish.outputs.download-url-exe-x64 }}
secrets: inherit
allowlist-exe-arm64:
uses: ./.github/workflows/av-whitelist.yml
needs: [ publish, allowlist-msi-arm64 ]
with:
url: ${{ needs.publish.outputs.download-url-exe-arm64 }}
secrets: inherit secrets: inherit
notify-winget: notify-winget:
@@ -413,7 +475,7 @@ jobs:
SLACK_ICON: false SLACK_ICON: false
SLACK_ICON_EMOJI: ':bot:' SLACK_ICON_EMOJI: ':bot:'
SLACK_CHANNEL: 'cryptomator-desktop' SLACK_CHANNEL: 'cryptomator-desktop'
SLACK_TITLE: "MSI of ${{ github.event.repository.name }} ${{ github.event.release.tag_name }} published." SLACK_TITLE: "MSI packages of ${{ github.event.repository.name }} ${{ github.event.release.tag_name }} published."
SLACK_MESSAGE: "Ready to <https://github.com/${{ github.repository }}/actions/workflows/winget.yml| release to winget>." SLACK_MESSAGE: "Ready to <https://github.com/${{ github.repository }}/actions/workflows/winget.yml| release them to winget>."
SLACK_FOOTER: false SLACK_FOOTER: false
MSG_MINIMAL: true MSG_MINIMAL: true
+1 -1
View File
@@ -23,5 +23,5 @@ jobs:
identifier: Cryptomator.Cryptomator identifier: Cryptomator.Cryptomator
version: ${{ inputs.tag }} version: ${{ inputs.tag }}
release-tag: ${{ inputs.tag }} release-tag: ${{ inputs.tag }}
installers-regex: '\.msi$' installers-regex: '-x64\.msi$'
token: ${{ secrets.CRYPTOBOT_WINGET_TOKEN }} token: ${{ secrets.CRYPTOBOT_WINGET_TOKEN }}
+1 -1
View File
@@ -8,7 +8,7 @@
</list> </list>
</option> </option>
</component> </component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_23" project-jdk-name="23" project-jdk-type="JavaSDK"> <component name="ProjectRootManager" version="2" languageLevel="JDK_24" project-jdk-name="24" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" /> <output url="file://$PROJECT_DIR$/out" />
</component> </component>
</project> </project>
+1 -1
View File
@@ -2,7 +2,7 @@
<configuration default="false" name="Cryptomator Linux" type="Application" factoryName="Application"> <configuration default="false" name="Cryptomator Linux" type="Application" factoryName="Application">
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" /> <option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
<module name="cryptomator" /> <module name="cryptomator" />
<option name="VM_PARAMETERS" value="-Dcryptomator.settingsPath=&quot;@{userhome}/.config/Cryptomator/settings.json&quot; -Dcryptomator.p12Path=&quot;@{userhome}/.config/Cryptomator/key.p12&quot; -Dcryptomator.ipcSocketPath=&quot;@{userhome}/.config/Cryptomator/ipc.socket&quot; -Dcryptomator.logDir=&quot;@{userhome}/.local/share/Cryptomator/logs&quot; -Dcryptomator.pluginDir=&quot;@{userhome}/.local/share/Cryptomator/plugins&quot; -Dcryptomator.mountPointsDir=&quot;@{userhome}/.local/share/Cryptomator/mnt&quot; -Dcryptomator.showTrayIcon=true -Xss20m -Xmx512m --enable-preview --enable-native-access=org.cryptomator.jfuse.linux.amd64,org.cryptomator.jfuse.linux.aarch64,org.purejava.appindicator" /> <option name="VM_PARAMETERS" value="-Dcryptomator.settingsPath=&quot;@{userhome}/.config/Cryptomator/settings.json&quot; -Dcryptomator.p12Path=&quot;@{userhome}/.config/Cryptomator/key.p12&quot; -Dcryptomator.ipcSocketPath=&quot;@{userhome}/.config/Cryptomator/ipc.socket&quot; -Dcryptomator.logDir=&quot;@{userhome}/.local/share/Cryptomator/logs&quot; -Dcryptomator.pluginDir=&quot;@{userhome}/.local/share/Cryptomator/plugins&quot; -Dcryptomator.mountPointsDir=&quot;@{userhome}/.local/share/Cryptomator/mnt&quot; -Dcryptomator.showTrayIcon=true -Xss20m -Xmx512m --enable-preview --enable-native-access=org.cryptomator.jfuse.linux.amd64,org.cryptomator.jfuse.linux.aarch64,org.purejava.appindicator,javafx.graphics" />
<method v="2"> <method v="2">
<option name="Make" enabled="true" /> <option name="Make" enabled="true" />
</method> </method>
+1 -1
View File
@@ -2,7 +2,7 @@
<configuration default="false" name="Cryptomator Linux Dev" type="Application" factoryName="Application"> <configuration default="false" name="Cryptomator Linux Dev" type="Application" factoryName="Application">
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" /> <option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
<module name="cryptomator" /> <module name="cryptomator" />
<option name="VM_PARAMETERS" value="-Dcryptomator.settingsPath=&quot;@{userhome}/.config/Cryptomator-Dev/settings.json&quot; -Dcryptomator.p12Path=&quot;@{userhome}/.config/Cryptomator-Dev/key.p12&quot; -Dcryptomator.ipcSocketPath=&quot;@{userhome}/.config/Cryptomator-Dev/ipc.socket&quot; -Dcryptomator.logDir=&quot;@{userhome}/.local/share/Cryptomator-Dev/logs&quot; -Dcryptomator.pluginDir=&quot;@{userhome}/.local/share/Cryptomator-Dev/plugins&quot; -Dcryptomator.mountPointsDir=&quot;@{userhome}/.local/share/Cryptomator-Dev/mnt&quot; -Dcryptomator.showTrayIcon=true -Dfuse.experimental=&quot;true&quot; -Xss20m -Xmx512m --enable-preview --enable-native-access=org.cryptomator.jfuse.linux.amd64,org.cryptomator.jfuse.linux.aarch64,org.purejava.appindicator" /> <option name="VM_PARAMETERS" value="-Dcryptomator.settingsPath=&quot;@{userhome}/.config/Cryptomator-Dev/settings.json&quot; -Dcryptomator.p12Path=&quot;@{userhome}/.config/Cryptomator-Dev/key.p12&quot; -Dcryptomator.ipcSocketPath=&quot;@{userhome}/.config/Cryptomator-Dev/ipc.socket&quot; -Dcryptomator.logDir=&quot;@{userhome}/.local/share/Cryptomator-Dev/logs&quot; -Dcryptomator.pluginDir=&quot;@{userhome}/.local/share/Cryptomator-Dev/plugins&quot; -Dcryptomator.mountPointsDir=&quot;@{userhome}/.local/share/Cryptomator-Dev/mnt&quot; -Dcryptomator.showTrayIcon=true -Dfuse.experimental=&quot;true&quot; -Xss20m -Xmx512m --enable-preview --enable-native-access=org.cryptomator.jfuse.linux.amd64,org.cryptomator.jfuse.linux.aarch64,org.purejava.appindicator,javafx.graphics" />
<method v="2"> <method v="2">
<option name="Make" enabled="true" /> <option name="Make" enabled="true" />
</method> </method>
+1 -1
View File
@@ -2,7 +2,7 @@
<configuration default="false" name="Cryptomator Windows" type="Application" factoryName="Application"> <configuration default="false" name="Cryptomator Windows" type="Application" factoryName="Application">
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" /> <option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
<module name="cryptomator" /> <module name="cryptomator" />
<option name="VM_PARAMETERS" value="-Dcryptomator.settingsPath=&quot;@{appdata}/Cryptomator/settings.json;@{userhome}/AppData/Roaming/Cryptomator/settings.json&quot; -Dcryptomator.ipcSocketPath=&quot;@{localappdata}/Cryptomator/ipc.socket&quot; -Dcryptomator.logDir=&quot;@{localappdata}/Cryptomator&quot; -Dcryptomator.pluginDir=&quot;@{appdata}/Cryptomator/Plugins&quot; -Dcryptomator.integrationsWin.keychainPaths=&quot;@{appdata}/Cryptomator/keychain.json;@{userhome}/AppData/Roaming/Cryptomator/keychain.json&quot; -Dcryptomator.p12Path=&quot;@{appdata}/Cryptomator/key.p12;@{userhome}/AppData/Roaming/Cryptomator/key.p12&quot; -Dcryptomator.mountPointsDir=&quot;@{userhome}/Cryptomator&quot; -Dcryptomator.showTrayIcon=true -Xss2m -Xmx512m --enable-preview --enable-native-access=org.cryptomator.jfuse.win,org.cryptomator.integrations.win" /> <option name="VM_PARAMETERS" value="-Dcryptomator.settingsPath=&quot;@{appdata}/Cryptomator/settings.json;@{userhome}/AppData/Roaming/Cryptomator/settings.json&quot; -Dcryptomator.ipcSocketPath=&quot;@{localappdata}/Cryptomator/ipc.socket&quot; -Dcryptomator.logDir=&quot;@{localappdata}/Cryptomator&quot; -Dcryptomator.pluginDir=&quot;@{appdata}/Cryptomator/Plugins&quot; -Dcryptomator.integrationsWin.keychainPaths=&quot;@{appdata}/Cryptomator/keychain.json;@{userhome}/AppData/Roaming/Cryptomator/keychain.json&quot; -Dcryptomator.integrationsWin.windowsHelloKeychainPaths=&quot;@{appdata}/Cryptomator/windowsHelloKeychain.json;@{userhome}/AppData/Roaming/Cryptomator/windowsHelloKeychain.json&quot; -Dcryptomator.p12Path=&quot;@{appdata}/Cryptomator/key.p12;@{userhome}/AppData/Roaming/Cryptomator/key.p12&quot; -Dcryptomator.mountPointsDir=&quot;@{userhome}/Cryptomator&quot; -Dcryptomator.showTrayIcon=true -Xss2m -Xmx512m --enable-preview --enable-native-access=org.cryptomator.jfuse.win,org.cryptomator.integrations.win,javafx.graphics" />
<method v="2"> <method v="2">
<option name="Make" enabled="true" /> <option name="Make" enabled="true" />
</method> </method>
+1 -1
View File
@@ -2,7 +2,7 @@
<configuration default="false" name="Cryptomator Windows Dev" type="Application" factoryName="Application"> <configuration default="false" name="Cryptomator Windows Dev" type="Application" factoryName="Application">
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" /> <option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
<module name="cryptomator" /> <module name="cryptomator" />
<option name="VM_PARAMETERS" value="-Dcryptomator.settingsPath=&quot;@{appdata}/Cryptomator-Dev/settings.json;@{userhome}/AppData/Roaming/Cryptomator-Dev/settings.json&quot; -Dcryptomator.ipcSocketPath=&quot;@{localappdata}/Cryptomator-Dev/ipc.socket&quot; -Dcryptomator.logDir=&quot;@{localappdata}/Cryptomator-Dev&quot; -Dcryptomator.pluginDir=&quot;@{appdata}/Cryptomator-Dev/Plugins&quot; -Dcryptomator.integrationsWin.keychainPaths=&quot;@{appdata}/Cryptomator-Dev/keychain.json;@{userhome}/AppData/Roaming/Cryptomator-Dev/keychain.json&quot; -Dcryptomator.p12Path=&quot;@{appdata}/Cryptomator-Dev/key.p12;@{userhome}/AppData/Roaming/Cryptomator-Dev/key.p12&quot; -Dcryptomator.mountPointsDir=&quot;@{userhome}/Cryptomator-Dev&quot; -Dcryptomator.showTrayIcon=true -Xss2m -Xmx512m --enable-preview --enable-native-access=org.cryptomator.jfuse.win,org.cryptomator.integrations.win" /> <option name="VM_PARAMETERS" value="-Dcryptomator.settingsPath=&quot;@{appdata}/Cryptomator-Dev/settings.json;@{userhome}/AppData/Roaming/Cryptomator-Dev/settings.json&quot; -Dcryptomator.ipcSocketPath=&quot;@{localappdata}/Cryptomator-Dev/ipc.socket&quot; -Dcryptomator.logDir=&quot;@{localappdata}/Cryptomator-Dev&quot; -Dcryptomator.pluginDir=&quot;@{appdata}/Cryptomator-Dev/Plugins&quot; -Dcryptomator.integrationsWin.keychainPaths=&quot;@{appdata}/Cryptomator-Dev/keychain.json;@{userhome}/AppData/Roaming/Cryptomator-Dev/keychain.json&quot; -Dcryptomator.integrationsWin.windowsHelloKeychainPaths=&quot;@{appdata}/Cryptomator-Dev/windowsHelloKeychain.json;@{userhome}/AppData/Roaming/Cryptomator-Dev/windowsHelloKeychain.json&quot; -Dcryptomator.p12Path=&quot;@{appdata}/Cryptomator-Dev/key.p12;@{userhome}/AppData/Roaming/Cryptomator-Dev/key.p12&quot; -Dcryptomator.mountPointsDir=&quot;@{userhome}/Cryptomator-Dev&quot; -Dcryptomator.showTrayIcon=true -Xss2m -Xmx512m --enable-preview --enable-native-access=org.cryptomator.jfuse.win,org.cryptomator.integrations.win,javafx.graphics" />
<method v="2"> <method v="2">
<option name="Make" enabled="true" /> <option name="Make" enabled="true" />
</method> </method>
+1 -1
View File
@@ -5,7 +5,7 @@
</envs> </envs>
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" /> <option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
<module name="cryptomator" /> <module name="cryptomator" />
<option name="VM_PARAMETERS" value="-Dapple.awt.enableTemplateImages=true -Dcryptomator.settingsPath=&quot;@{userhome}/Library/Application Support/Cryptomator/settings.json&quot; -Dcryptomator.p12Path=&quot;@{userhome}/Library/Application Support/Cryptomator/key.p12&quot; -Dcryptomator.ipcSocketPath=&quot;@{userhome}/Library/Application Support/Cryptomator/ipc.socket&quot; -Dcryptomator.logDir=&quot;@{userhome}/Library/Logs/Cryptomator&quot; -Dcryptomator.pluginDir=&quot;@{userhome}/Library/Application Support/Cryptomator/Plugins&quot; -Dcryptomator.mountPointsDir=&quot;@{userhome}/Cryptomator&quot; -Dcryptomator.showTrayIcon=true -Dcryptomator.integrationsMac.keychainServiceName=Cryptomator -Xss2m -Xmx512m -ea --enable-preview --enable-native-access=org.cryptomator.jfuse.mac" /> <option name="VM_PARAMETERS" value="-Dapple.awt.enableTemplateImages=true -Dcryptomator.settingsPath=&quot;@{userhome}/Library/Application Support/Cryptomator/settings.json&quot; -Dcryptomator.p12Path=&quot;@{userhome}/Library/Application Support/Cryptomator/key.p12&quot; -Dcryptomator.ipcSocketPath=&quot;@{userhome}/Library/Application Support/Cryptomator/ipc.socket&quot; -Dcryptomator.logDir=&quot;@{userhome}/Library/Logs/Cryptomator&quot; -Dcryptomator.pluginDir=&quot;@{userhome}/Library/Application Support/Cryptomator/Plugins&quot; -Dcryptomator.mountPointsDir=&quot;@{userhome}/Cryptomator&quot; -Dcryptomator.showTrayIcon=true -Dcryptomator.integrationsMac.keychainServiceName=Cryptomator -Xss2m -Xmx512m -ea --enable-preview --enable-native-access=org.cryptomator.jfuse.mac,javafx.graphics" />
<method v="2"> <method v="2">
<option name="Make" enabled="true" /> <option name="Make" enabled="true" />
</method> </method>
+1 -1
View File
@@ -5,7 +5,7 @@
</envs> </envs>
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" /> <option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
<module name="cryptomator" /> <module name="cryptomator" />
<option name="VM_PARAMETERS" value="-Dapple.awt.enableTemplateImages=true -Dcryptomator.settingsPath=&quot;@{userhome}/Library/Application Support/Cryptomator-Dev/settings.json&quot; -Dcryptomator.p12Path=&quot;@{userhome}/Library/Application Support/Cryptomator-Dev/key.p12&quot; -Dcryptomator.ipcSocketPath=&quot;@{userhome}/Library/Application Support/Cryptomator-Dev/ipc.socket&quot; -Dcryptomator.logDir=&quot;@{userhome}/Library/Logs/Cryptomator-Dev&quot; -Dcryptomator.pluginDir=&quot;@{userhome}/Library/Application Support/Cryptomator-Dev/Plugins&quot; -Dcryptomator.mountPointsDir=&quot;@{userhome}/Library/Application Support/Cryptomator-Dev/mnt&quot; -Dcryptomator.showTrayIcon=true -Dcryptomator.integrationsMac.keychainServiceName=Cryptomator -Xss2m -Xmx512m -ea --enable-preview --enable-native-access=org.cryptomator.jfuse.mac" /> <option name="VM_PARAMETERS" value="-Dapple.awt.enableTemplateImages=true -Dcryptomator.settingsPath=&quot;@{userhome}/Library/Application Support/Cryptomator-Dev/settings.json&quot; -Dcryptomator.p12Path=&quot;@{userhome}/Library/Application Support/Cryptomator-Dev/key.p12&quot; -Dcryptomator.ipcSocketPath=&quot;@{userhome}/Library/Application Support/Cryptomator-Dev/ipc.socket&quot; -Dcryptomator.logDir=&quot;@{userhome}/Library/Logs/Cryptomator-Dev&quot; -Dcryptomator.pluginDir=&quot;@{userhome}/Library/Application Support/Cryptomator-Dev/Plugins&quot; -Dcryptomator.mountPointsDir=&quot;@{userhome}/Library/Application Support/Cryptomator-Dev/mnt&quot; -Dcryptomator.showTrayIcon=true -Dcryptomator.integrationsMac.keychainServiceName=Cryptomator -Xss2m -Xmx512m -ea --enable-preview --enable-native-access=org.cryptomator.jfuse.mac,javafx.graphics" />
<method v="2"> <method v="2">
<option name="Make" enabled="true" /> <option name="Make" enabled="true" />
</method> </method>
+1 -1
View File
@@ -78,7 +78,7 @@ For more information on the security details visit [cryptomator.org](https://doc
### Dependencies ### Dependencies
* JDK 23 (e.g. temurin, zulu) * JDK 24 (e.g. temurin, zulu)
* Maven 3 * Maven 3
### Run Maven ### Run Maven
+12 -6
View File
@@ -23,12 +23,12 @@ mvn -B -f ../../../pom.xml clean package -Plinux -DskipTests -Djavafx.platform=l
cp ../../../LICENSE.txt ../../../target cp ../../../LICENSE.txt ../../../target
cp ../../../target/cryptomator-*.jar ../../../target/mods cp ../../../target/cryptomator-*.jar ../../../target/mods
JAVAFX_VERSION=22.0.2 JAVAFX_VERSION=24.0.1
JAVAFX_ARCH="x64" JAVAFX_ARCH="x64"
JAVAFX_JMODS_SHA256='2164bca470bf70a5e2764645e2078ba7f787b274e5be3d7df30d87c5bb62bba6' JAVAFX_JMODS_SHA256='425fac742b9fbd095b2ce868cff82d1024620f747c94a7144d0a4879e756146c'
if [ "${CPU_ARCH}" = "aarch64" ]; then if [ "${CPU_ARCH}" = "aarch64" ]; then
JAVAFX_ARCH="aarch64" JAVAFX_ARCH="aarch64"
JAVAFX_JMODS_SHA256='09c92fa9fa0b82adefd88640a14ebb2a49e5f3f733a57d1542f5590d060ffe1b' JAVAFX_JMODS_SHA256='7e02edd0f4ee5527a27c94b0bbba66fcaaff41009119e45d0eca0f96ddfb6e7b'
fi fi
# download javaFX jmods # download javaFX jmods
@@ -51,11 +51,17 @@ if [ $POM_JFX_VERSION -ne $JMOD_VERSION ]; then
fi fi
# add runtime # create runtime
## check for JEP 493
JMOD_PATHS="openjfx-jmods"
if ! ${JAVA_HOME}/bin/jlink --help | grep -q "Linking from run-time image enabled"; then
JMOD_PATHS="${JAVA_HOME}/jmods:${JMOD_PATHS}"
fi
## create runtime image
${JAVA_HOME}/bin/jlink \ ${JAVA_HOME}/bin/jlink \
--verbose \ --verbose \
--output runtime \ --output runtime \
--module-path "${JAVA_HOME}/jmods:openjfx-jmods" \ --module-path "${JMOD_PATHS}" \
--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.security.auth,jdk.accessibility,jdk.management.jfr,jdk.net,java.compiler \ --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.security.auth,jdk.accessibility,jdk.management.jfr,jdk.net,java.compiler \
--strip-native-commands \ --strip-native-commands \
--no-header-files \ --no-header-files \
@@ -75,7 +81,7 @@ ${JAVA_HOME}/bin/jpackage \
--name Cryptomator \ --name Cryptomator \
--vendor "Skymatic GmbH" \ --vendor "Skymatic GmbH" \
--java-options "--enable-preview" \ --java-options "--enable-preview" \
--java-options "--enable-native-access=org.cryptomator.jfuse.linux.amd64,org.cryptomator.jfuse.linux.aarch64,org.purejava.appindicator" \ --java-options "--enable-native-access=javafx.graphics,org.cryptomator.jfuse.linux.amd64,org.cryptomator.jfuse.linux.aarch64,org.purejava.appindicator" \
--copyright "(C) 2016 - 2025 Skymatic GmbH" \ --copyright "(C) 2016 - 2025 Skymatic GmbH" \
--java-options "-Xss5m" \ --java-options "-Xss5m" \
--java-options "-Xmx256m" \ --java-options "-Xmx256m" \
@@ -83,6 +83,21 @@
</content_rating> </content_rating>
<releases> <releases>
<release date="2025-05-15" version="1.16.2">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.16.2</url>
</release>
<release date="2025-04-30" version="1.16.1">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.16.1</url>
</release>
<release date="2025-04-29" version="1.16.0">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.16.0</url>
</release>
<release date="2025-04-09" version="1.15.3">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.15.3</url>
</release>
<release date="2025-04-04" version="1.15.2">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.15.2</url>
</release>
<release date="2025-02-05" version="1.15.1"> <release date="2025-02-05" version="1.15.1">
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.15.1</url> <url type="details">https://github.com/cryptomator/cryptomator/releases/1.15.1</url>
</release> </release>
+1 -1
View File
@@ -1,4 +1,4 @@
cryptomator (${PPA_VERSION}) focal; urgency=low cryptomator (${PPA_VERSION}) jammy; urgency=low
* Full changelog can be found on https://github.com/cryptomator/cryptomator/releases * Full changelog can be found on https://github.com/cryptomator/cryptomator/releases
+1 -1
View File
@@ -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-23 (>= 23.0.1+11-0ppa1), libgtk-3-0, libxxf86vm1, libgl1 Build-Depends: debhelper (>=10), coffeelibs-jdk-24 (>= 24.0.1+9-0ppa3), 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
+2 -2
View File
@@ -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-23-coffeelibs JAVA_HOME = /usr/lib/jvm/java-24-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
@@ -44,7 +44,7 @@ override_dh_auto_build:
--name cryptomator \ --name cryptomator \
--vendor "Skymatic GmbH" \ --vendor "Skymatic GmbH" \
--java-options "--enable-preview" \ --java-options "--enable-preview" \
--java-options "--enable-native-access=org.cryptomator.jfuse.linux.amd64,org.cryptomator.jfuse.linux.aarch64,org.purejava.appindicator" \ --java-options "--enable-native-access=javafx.graphics,org.cryptomator.jfuse.linux.amd64,org.cryptomator.jfuse.linux.aarch64,org.purejava.appindicator" \
--copyright "(C) 2016 - 2025 Skymatic GmbH" \ --copyright "(C) 2016 - 2025 Skymatic GmbH" \
--java-options "-Xss5m" \ --java-options "-Xss5m" \
--java-options "-Xmx256m" \ --java-options "-Xmx256m" \
+12 -6
View File
@@ -32,15 +32,15 @@ REVISION_NO=`git rev-list --count HEAD`
VERSION_NO=`mvn -f../../../pom.xml help:evaluate -Dexpression=project.version -q -DforceStdout | sed -rn 's/.*([0-9]+\.[0-9]+\.[0-9]+).*/\1/p'` VERSION_NO=`mvn -f../../../pom.xml help:evaluate -Dexpression=project.version -q -DforceStdout | sed -rn 's/.*([0-9]+\.[0-9]+\.[0-9]+).*/\1/p'`
FUSE_LIB="FUSE-T" FUSE_LIB="FUSE-T"
JAVAFX_VERSION=23.0.1 JAVAFX_VERSION=24.0.1
JAVAFX_ARCH="undefined" JAVAFX_ARCH="undefined"
JAVAFX_JMODS_SHA256="undefined" JAVAFX_JMODS_SHA256="undefined"
if [ "$(machine)" = "arm64e" ]; then if [ "$(machine)" = "arm64e" ]; then
JAVAFX_ARCH="aarch64" JAVAFX_ARCH="aarch64"
JAVAFX_JMODS_SHA256="a800724a1f3e6757ecfa0bd5bf7ed64d2e6a7a3f5b3522650a70b8cfc7782fb6" JAVAFX_JMODS_SHA256="b5a94a13077507003fa852512bfa33f4fb680bc8076d8002e4227a84c85171d4"
else else
JAVAFX_ARCH="x64" JAVAFX_ARCH="x64"
JAVAFX_JMODS_SHA256="8857965975c464a0e5d57709292ce357d0ebb39f6168c41d5ca38301e42c3c8e" JAVAFX_JMODS_SHA256="6e62a426d43c168a488521f904a523f3dd6ee2cf103e08136f2fd465c828a105"
fi fi
JAVAFX_JMODS_URL="https://download2.gluonhq.com/openjfx/${JAVAFX_VERSION}/openjfx-${JAVAFX_VERSION}_osx-${JAVAFX_ARCH}_bin-jmods.zip" JAVAFX_JMODS_URL="https://download2.gluonhq.com/openjfx/${JAVAFX_VERSION}/openjfx-${JAVAFX_VERSION}_osx-${JAVAFX_ARCH}_bin-jmods.zip"
@@ -75,10 +75,16 @@ mvn -B -Djavafx.platform=mac -f../../../pom.xml clean package -DskipTests -Pmac
cp ../../../LICENSE.txt ../../../target cp ../../../LICENSE.txt ../../../target
cp ../../../target/${MAIN_JAR_GLOB} ../../../target/mods cp ../../../target/${MAIN_JAR_GLOB} ../../../target/mods
# add runtime # create runtime
## check for JEP 493
JMOD_PATHS="openjfx-jmods"
if ! ${JAVA_HOME}/bin/jlink --help | grep -q "Linking from run-time image enabled"; then
JMOD_PATHS="${JAVA_HOME}/jmods:${JMOD_PATHS}"
fi
## create custom runtime
${JAVA_HOME}/bin/jlink \ ${JAVA_HOME}/bin/jlink \
--output runtime \ --output runtime \
--module-path "${JAVA_HOME}/jmods:openjfx-jmods" \ --module-path "${JMOD_PATHS}" \
--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.security.auth,jdk.accessibility,jdk.management.jfr,java.compiler \ --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.security.auth,jdk.accessibility,jdk.management.jfr,java.compiler \
--strip-native-commands \ --strip-native-commands \
--no-header-files \ --no-header-files \
@@ -100,7 +106,7 @@ ${JAVA_HOME}/bin/jpackage \
--copyright "(C) ${COPYRIGHT_YEARS} ${VENDOR}" \ --copyright "(C) ${COPYRIGHT_YEARS} ${VENDOR}" \
--app-version "${VERSION_NO}" \ --app-version "${VERSION_NO}" \
--java-options "--enable-preview" \ --java-options "--enable-preview" \
--java-options "--enable-native-access=org.cryptomator.jfuse.mac" \ --java-options "--enable-native-access=javafx.graphics,org.cryptomator.jfuse.mac" \
--java-options "-Xss5m" \ --java-options "-Xss5m" \
--java-options "-Xmx256m" \ --java-options "-Xmx256m" \
--java-options "-Dfile.encoding=\"utf-8\"" \ --java-options "-Dfile.encoding=\"utf-8\"" \
+94 -30
View File
@@ -18,14 +18,32 @@ $ProgressPreference = 'SilentlyContinue' # disables Invoke-WebRequest's progress
# check preconditions # check preconditions
if ((Get-Command "git" -ErrorAction SilentlyContinue) -eq $null) if ((Get-Command "git" -ErrorAction SilentlyContinue) -eq $null)
{ {
Write-Host "Unable to find git.exe in your PATH (try: choco install git)" Write-Error "Unable to find git.exe in your PATH (try: choco install git)"
exit 1 exit 1
} }
if ((Get-Command "mvn" -ErrorAction SilentlyContinue) -eq $null) if ((Get-Command "mvn" -ErrorAction SilentlyContinue) -eq $null)
{ {
Write-Host "Unable to find mvn.cmd in your PATH (try: choco install maven)" Write-Error "Unable to find mvn.cmd in your PATH (try: choco install maven)"
exit 1 exit 1
} }
if ((Get-Command 'wix' -ErrorAction SilentlyContinue) -eq $null)
{
Write-Error 'Unable to find wix in your PATH (try: dotnet tool install --global wix --version 6.0.0)'
exit 1
}
$wixExtensions = & wix.exe extension list --global | Out-String
if ($wixExtensions -notmatch 'WixToolset.UI.wixext') {
Write-Error 'Wix UI extension missing. Please install it with: wix.exe extension add WixToolset.UI.wixext/6.0.0 --global)'
exit 1
}
if ($wixExtensions -notmatch 'WixToolset.Util.wixext') {
Write-Error 'Wix Util extension missing. Please install it with: wix.exe extension add WixToolset.Util.wixext/6.0.0 --global)'
exit 1
}
if ($wixExtensions -notmatch 'WixToolset.BootstrapperApplications.wixext') {
Write-Error 'Wix Bootstrapper extension missing. Please install it with: wix.exe extension add WixToolset.BootstrapperApplications.wixext/6.0.0 --global)'
exit 1
}
$buildDir = Split-Path -Parent $PSCommandPath $buildDir = Split-Path -Parent $PSCommandPath
$version = $(mvn -f $buildDir/../../pom.xml help:evaluate -Dexpression="project.version" -q -DforceStdout) $version = $(mvn -f $buildDir/../../pom.xml help:evaluate -Dexpression="project.version" -q -DforceStdout)
@@ -50,37 +68,71 @@ if ($clean -and (Test-Path -Path $runtimeImagePath)) {
Remove-Item -Path $runtimeImagePath -Force -Recurse Remove-Item -Path $runtimeImagePath -Force -Recurse
} }
## download jfx jmods ## download jfx jmods for X64, while they are part of the Arm64 JDK
$javaFxVersion='23.0.1' $archCode = (Get-CimInstance Win32_Processor).Architecture
$javaFxJmodsUrl = "https://download2.gluonhq.com/openjfx/${javaFxVersion}/openjfx-${javaFxVersion}_windows-x64_bin-jmods.zip" $archName = switch ($archCode) {
$javaFxJmodsSHA256 = 'ee176dcee3bd78bde7910735bd67f67c792882f5b89626796ae06f7a1c0119d3' 9 { "x64 (AMD64)" }
$javaFxJmods = '.\resources\jfxJmods.zip' 12 { "ARM64" }
if( !(Test-Path -Path $javaFxJmods) ) { default { "WMI Win32_Processor.Architecture code ($archCode)" }
Write-Output "Downloading ${javaFxJmodsUrl}..."
Invoke-WebRequest $javaFxJmodsUrl -OutFile $javaFxJmods # redirects are followed by default
} }
$jmodsChecksumActual = $(Get-FileHash -Path $javaFxJmods -Algorithm SHA256).Hash.ToLower() switch ($archName) {
if( $jmodsChecksumActual -ne $javaFxJmodsSHA256 ) { 'ARM64' {
Write-Error "Checksum mismatch for jfxJmods.zip. Expected: $javaFxJmodsSHA256 $javafxBaseJmod = Join-Path $Env:JAVA_HOME "jmods\javafx.base.jmod"
, actual: $jmodsChecksumActual" if (!(Test-Path $javafxBaseJmod)) {
exit 1; Write-Error "JavaFX module not found in JDK. Please ensure full JDK (including jmods) is installed."
exit 1
}
$jmodPaths = "$Env:JAVA_HOME/jmods"
}
'x64 (AMD64)' {
$javaFxVersion='24.0.1'
$javaFxJmodsUrl = "https://download2.gluonhq.com/openjfx/${javaFxVersion}/openjfx-${javaFxVersion}_windows-x64_bin-jmods.zip"
$javaFxJmodsSHA256 = 'f13d17c7caf88654fc835f1b4e75a9b0f34a888eb8abef381796c0002e63b03f'
$javaFxJmods = '.\resources\jfxJmods.zip'
if( !(Test-Path -Path $javaFxJmods) ) {
Write-Output "Downloading ${javaFxJmodsUrl}..."
Invoke-WebRequest $javaFxJmodsUrl -OutFile $javaFxJmods # redirects are followed by default
}
$jmodsChecksumActual = $(Get-FileHash -Path $javaFxJmods -Algorithm SHA256).Hash.ToLower()
if( $jmodsChecksumActual -ne $javaFxJmodsSHA256 ) {
Write-Error "Checksum mismatch for jfxJmods.zip. Expected: $javaFxJmodsSHA256
, actual: $jmodsChecksumActual"
exit 1;
}
Expand-Archive -Path $javaFxJmods -Force -DestinationPath ".\resources\"
Remove-Item -Recurse -Force -Path ".\resources\javafx-jmods" -ErrorAction Ignore
Move-Item -Force -Path ".\resources\javafx-jmods-*" -Destination ".\resources\javafx-jmods" -ErrorAction Stop
$jmodPaths="$buildDir/resources/javafx-jmods";
}
default {
Write-Error "Unsupported architecture: $arch"
exit 1
}
} }
Expand-Archive -Path $javaFxJmods -Force -DestinationPath ".\resources\"
Remove-Item -Recurse -Force -Path ".\resources\javafx-jmods" -ErrorAction Ignore
Move-Item -Force -Path ".\resources\javafx-jmods-*" -Destination ".\resources\javafx-jmods" -ErrorAction Stop
## create custom runtime ## create custom runtime
### check for JEP 493
if ((& "$Env:JAVA_HOME\bin\jlink" --help | Select-String -Pattern "Linking from run-time image enabled" -SimpleMatch | Measure-Object).Count -eq 0 ) {
$jmodPaths="$Env:JAVA_HOME/jmods;" + $jmodPaths;
}
### create runtime
& "$Env:JAVA_HOME\bin\jlink" ` & "$Env:JAVA_HOME\bin\jlink" `
--verbose ` --verbose `
--output runtime ` --output runtime `
--module-path "$Env:JAVA_HOME/jmods;$buildDir/resources/javafx-jmods" ` --module-path $jmodPaths `
--add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,jdk.unsupported,jdk.accessibility,jdk.management.jfr,jdk.crypto.mscapi,java.compiler,javafx.base,javafx.graphics,javafx.controls,javafx.fxml ` --add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,jdk.unsupported,jdk.accessibility,jdk.management.jfr,jdk.crypto.mscapi,java.compiler,javafx.base,javafx.graphics,javafx.controls,javafx.fxml `
--strip-native-commands ` --strip-native-commands `
--no-header-files ` --no-header-files `
--no-man-pages ` --no-man-pages `
--strip-debug ` --strip-debug `
--compress "zip-0" #do not compress to have improved msi compression --compress "zip-0" #do not compress and use msi compression
$appPath = ".\$AppName" $appPath = ".\$AppName"
if ($clean -and (Test-Path -Path $appPath)) { if ($clean -and (Test-Path -Path $appPath)) {
@@ -100,7 +152,7 @@ if ($clean -and (Test-Path -Path $appPath)) {
--vendor $Vendor ` --vendor $Vendor `
--copyright $copyright ` --copyright $copyright `
--java-options "--enable-preview" ` --java-options "--enable-preview" `
--java-options "--enable-native-access=org.cryptomator.jfuse.win,org.cryptomator.integrations.win" ` --java-options "--enable-native-access=javafx.graphics,org.cryptomator.jfuse.win,org.cryptomator.integrations.win" `
--java-options "-Xss5m" ` --java-options "-Xss5m" `
--java-options "-Xmx256m" ` --java-options "-Xmx256m" `
--java-options "-Dcryptomator.appVersion=`"$semVerNo`"" ` --java-options "-Dcryptomator.appVersion=`"$semVerNo`"" `
@@ -116,6 +168,7 @@ if ($clean -and (Test-Path -Path $appPath)) {
--java-options "-Dcryptomator.loopbackAlias=`"$LoopbackAlias`"" ` --java-options "-Dcryptomator.loopbackAlias=`"$LoopbackAlias`"" `
--java-options "-Dcryptomator.integrationsWin.autoStartShellLinkName=`"$AppName`"" ` --java-options "-Dcryptomator.integrationsWin.autoStartShellLinkName=`"$AppName`"" `
--java-options "-Dcryptomator.integrationsWin.keychainPaths=`"@{appdata}/$AppName/keychain.json;@{userhome}/AppData/Roaming/$AppName/keychain.json`"" ` --java-options "-Dcryptomator.integrationsWin.keychainPaths=`"@{appdata}/$AppName/keychain.json;@{userhome}/AppData/Roaming/$AppName/keychain.json`"" `
--java-options "-Dcryptomator.integrationsWin.windowsHelloKeychainPaths=`"@{appdata}/$AppName/windowsHelloKeychain.json`"" `
--java-options "-Dcryptomator.showTrayIcon=true" ` --java-options "-Dcryptomator.showTrayIcon=true" `
--java-options "-Dcryptomator.buildNumber=`"msi-$revisionNo`"" ` --java-options "-Dcryptomator.buildNumber=`"msi-$revisionNo`"" `
--resource-dir resources ` --resource-dir resources `
@@ -166,6 +219,11 @@ $Env:JP_WIXHELPER_DIR = "."
--about-url $AboutUrl ` --about-url $AboutUrl `
--file-associations resources/FAvaultFile.properties --file-associations resources/FAvaultFile.properties
if ($LASTEXITCODE -ne 0) {
Write-Error "jpackage MSI failed with exit code $LASTEXITCODE"
return 1;
}
#Create RTF license for bundle #Create RTF license for bundle
&mvn -B -f $buildDir/../../pom.xml license:add-third-party "-Djavafx.platform=win" ` &mvn -B -f $buildDir/../../pom.xml license:add-third-party "-Djavafx.platform=win" `
"-Dlicense.thirdPartyFilename=license.rtf" ` "-Dlicense.thirdPartyFilename=license.rtf" `
@@ -187,14 +245,20 @@ Write-Output "Downloading ${winfspUninstaller}..."
Invoke-WebRequest $winfspUninstaller -OutFile ".\bundle\resources\winfsp-uninstaller.exe" # redirects are followed by default Invoke-WebRequest $winfspUninstaller -OutFile ".\bundle\resources\winfsp-uninstaller.exe" # redirects are followed by default
# copy MSI to bundle resources # copy MSI to bundle resources
Copy-Item ".\installer\$AppName-*.msi" -Destination ".\bundle\resources\$AppName.msi" Copy-Item ".\installer\$AppName-*.msi" -Destination ".\bundle\resources\$AppName.msi" -Force
# create bundle including winfsp # create bundle including winfsp
& "$env:WIX\bin\candle.exe" .\bundle\bundleWithWinfsp.wxs -ext WixBalExtension -ext WixUtilextension -out bundle\ ` & wix build `
-dBundleVersion="$semVerNo.$revisionNo" ` -define BundleName="$AppName" `
-dBundleVendor="$Vendor" ` -define BundleVersion="$semVerNo.$revisionNo" `
-dBundleCopyright="$copyright" ` -define BundleVendor="$Vendor" `
-dAboutUrl="$AboutUrl" ` -define BundleCopyright="$copyright" `
-dHelpUrl="$HelpUrl" ` -define AboutUrl="$AboutUrl" `
-dUpdateUrl="$UpdateUrl" -define HelpUrl="$HelpUrl" `
& "$env:WIX\bin\light.exe" -b . .\bundle\BundlewithWinfsp.wixobj -ext WixBalExtension -ext WixUtilextension -out installer\$AppName-Installer.exe -define UpdateUrl="$UpdateUrl" `
-ext "WixToolset.Util.wixext" `
-ext "WixToolset.BootstrapperApplications.wixext" `
.\bundle\bundleWithWinfsp.wxs `
-out "installer\$AppName-Installer.exe"
Write-Output "Created EXE installer .\installer\$AppName-Installer.exe"
+41 -59
View File
@@ -1,66 +1,48 @@
<?xml version="1.0"?> <!-- For Built in variables, see https://wixtoolset.org/docs/tools/burn/builtin-variables/-->
<ns0:Wix xmlns:ns0="http://wixtoolset.org/schemas/v4/wxs" xmlns:bal="http://wixtoolset.org/schemas/v4/wxs/bal" xmlns:util="http://wixtoolset.org/schemas/v4/wxs/util">
<!-- For Built in variables, see https://wixtoolset.org/docs/tools/burn/builtin-variables/--> <ns0:Bundle Name="$(var.BundleName)"
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:bal="http://schemas.microsoft.com/wix/BalExtension" xmlns:util="http://schemas.microsoft.com/wix/UtilExtension"> UpgradeCode="29eea626-2e5b-4449-b5f8-4602925ddf7b"
<!-- see https://wixtoolset.org/documentation/manual/v3/xsd/wix/bundle.html--> Version="$(var.BundleVersion)"
<!-- Attributes explicitly not used: Manufacturer="$(var.BundleVendor)"
Condition - the single msi files have their own install conditions, no need to copy them here AboutUrl="$(var.AboutUrl)"
--> HelpUrl="$(var.HelpUrl)"
UpdateUrl="$(var.UpdateUrl)"
<Bundle Name="Cryptomator" UpgradeCode="29eea626-2e5b-4449-b5f8-4602925ddf7b" Version="$(var.BundleVersion)" Manufacturer="$(var.BundleVendor)" Copyright="$(var.BundleCopyright)"
AboutUrl="$(var.AboutUrl)" HelpUrl="$(var.HelpUrl)" UpdateUrl="$(var.UpdateUrl)" Copyright="$(var.BundleCopyright)" IconSourceFile="bundle\resources\Cryptomator.ico"> IconSourceFile="bundle\resources\Cryptomator.ico">
<!-- detect outdated WinFsp installations --> <!-- detect outdated WinFsp installations -->
<util:ProductSearch <util:ProductSearch Variable="InstalledLegacyWinFspVersion" Result="version" UpgradeCode="82F812D9-4083-4EF1-8BC8-0F1EDA05B46B" />
Variable="InstalledLegacyWinFspVersion"
Result="version"
UpgradeCode="82F812D9-4083-4EF1-8BC8-0F1EDA05B46B"/>
<!-- for definition of the standard themes, see https://github.com/wixtoolset/wix3/blob/master/src/ext/BalExtension/wixstdba/Resources/--> <ns0:BootstrapperApplication>
<BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLargeLicense"> <bal:WixStandardBootstrapperApplication LicenseFile="bundle\resources\license.rtf" ShowVersion="yes"
<!-- see https://wixtoolset.org/documentation/manual/v3/xsd/bal/wixstandardbootstrapperapplication.html --> SuppressOptionsUI="yes"
<!-- Possible Attributes: LaunchTarget --> Theme="rtfLargeLicense"
<bal:WixStandardBootstrapperApplication ThemeFile="bundle\resources\customBootstrapperTheme.xml"
LicenseFile="bundle\resources\license.rtf" LocalizationFile="bundle\resources\customBootstrapperTheme.wxl"
ShowVersion="yes" LogoSideFile="bundle\resources\logoSide.png"
SuppressOptionsUI="yes" LogoFile="bundle\resources\logo.png"
ThemeFile="bundle\customBootstrapperTheme.xml" LaunchTarget="[ProgramFiles64Folder]\$(var.BundleName)\$(var.BundleName).exe" />
LocalizationFile="bundle\customBootstrapperTheme.wxl" <ns0:Payload SourceFile="bundle\resources\logoSide.png"/>
LogoFile="bundle\resources\logo.png"/> <!-- Required due to https://github.com/wixtoolset/issues/issues/8104 -->
<Payload SourceFile="bundle\resources\logoSide.png" /> <ns0:Payload Name="Cryptobot.ico" SourceFile="bundle\resources\Cryptomator.ico"/>
</BootstrapperApplicationRef> </ns0:BootstrapperApplication>
<Chain> <ns0:Chain>
<ExePackage Cache="yes" PerMachine="yes" Permanent="no" <ns0:ExePackage Cache="keep" PerMachine="yes" Permanent="no" SourceFile="bundle\resources\winfsp-uninstaller.exe" DisplayName="Removing outdated WinFsp Driver" Description="Executable to remove old winfsp" DetectCondition="false" InstallCondition="(InstalledLegacyWinFspVersion &lt;&gt; v0.0.0.0) AND ((WixBundleAction = 7) OR (WixBundleAction = 5))" UninstallArguments="">
SourceFile="resources\winfsp-uninstaller.exe" <ns0:CommandLine Condition="WixBundleUILevel &lt;= 3" InstallArgument="-q -l &quot;[WixBundleLog].winfsp-uninstaller.log&quot;" RepairArgument="-q" UninstallArgument="-s" />
DisplayName="Removing outdated WinFsp Driver"
Description="Executable to remove old winfsp"
DetectCondition="false"
InstallCondition="(InstalledLegacyWinFspVersion &lt;&gt; v0.0.0.0) AND ((WixBundleAction = 7) OR (WixBundleAction = 5))">
<CommandLine Condition="WixBundleUILevel &lt;= 3" InstallArgument="-q -l &quot;[WixBundleLog].winfsp-uninstaller.log&quot;" RepairArgument="-q" UninstallArgument="-s" />
<!-- XML allows line breaks in attributes, hence keep the line breaks here --> <!-- XML allows line breaks in attributes, hence keep the line breaks here -->
<CommandLine Condition="WixBundleUILevel &gt; 3" InstallArgument="-l &quot;[WixBundleLog].winfsp-uninstaller.log&quot; -t &quot;Cryptomator Installer&quot; -m &quot;Cryptomator requires a newer version of the WinFsp driver. The installer will now uninstall WinFsp, possibly reboot, and afterwards proceed with the installation. <ns0:CommandLine Condition="WixBundleUILevel &gt; 3" InstallArgument="-l &quot;[WixBundleLog].winfsp-uninstaller.log&quot; -t &quot;Cryptomator Installer&quot; -m &quot;Cryptomator requires a newer version of the WinFsp driver. The installer will now uninstall WinFsp, possibly reboot, and afterwards proceed with the installation.
Do you want to continue?&quot;" RepairArgument="-q" UninstallArgument="-s" /> Do you want to continue?&quot;" RepairArgument="-q" UninstallArgument="-s" />
<ExitCode Behavior="success" Value="0"/> <ns0:ExitCode Behavior="success" Value="0" />
<ExitCode Behavior="success" Value="1"/> <ns0:ExitCode Behavior="success" Value="1" />
<ExitCode Behavior="error" Value="2"/> <ns0:ExitCode Behavior="error" Value="2" />
<ExitCode Behavior="error" Value="3"/> <ns0:ExitCode Behavior="error" Value="3" />
<ExitCode Behavior="forceReboot" Value="4"/> <ns0:ExitCode Behavior="forceReboot" Value="4" />
<ExitCode Behavior="success" Value="5"/> <ns0:ExitCode Behavior="success" Value="5" />
</ExePackage> </ns0:ExePackage>
<!-- see https://wixtoolset.org/documentation/manual/v3/xsd/wix/msipackage.html--> <ns0:MsiPackage SourceFile="bundle\resources\Cryptomator.msi" CacheId="cryptomator-bundle-cryptomator" Visible="no" />
<MsiPackage <ns0:MsiPackage SourceFile="bundle\resources\winfsp.msi" CacheId="cryptomator-bundle-winfsp" Visible="yes" Permanent="yes" />
SourceFile="resources\Cryptomator.msi" </ns0:Chain>
CacheId="cryptomator-bundle-cryptomator" </ns0:Bundle>
DisplayInternalUI="no" </ns0:Wix>
Visible="no"/>
<MsiPackage
SourceFile="resources\winfsp.msi"
CacheId="cryptomator-bundle-winfsp"
Visible="yes"
DisplayInternalUI="no"
Permanent="yes"/>
</Chain>
</Bundle>
</Wix>
-64
View File
@@ -1,64 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
<WixLocalization Culture="en-us" Language="1033" xmlns="http://schemas.microsoft.com/wix/2006/localization">
<String Id="Caption">[WixBundleName] Setup</String>
<String Id="Title">[WixBundleName]</String>
<String Id="InstallHeader">Welcome</String>
<String Id="InstallMessage">This Setup will install [WixBundleName] and additional dependencies on your computer.</String>
<String Id="InstallVersion">Version [WixBundleVersion]</String>
<String Id="ConfirmCancelMessage">Are you sure you want to cancel?</String>
<String Id="ExecuteUpgradeRelatedBundleMessage">Previous version</String>
<String Id="HelpHeader">Setup Help</String>
<String Id="HelpText">/install | /repair | /uninstall | /layout [directory] - installs, repairs, uninstalls or
creates a complete local copy of the bundle in directory. Install is the default.
/passive | /quiet - displays minimal UI with no prompts or displays no UI and
no prompts. By default UI and all prompts are displayed.
/norestart - suppress any attempts to restart. By default UI will prompt before restart.
/log log.txt - logs to a specific file. By default a log file is created in %TEMP%.</String>
<String Id="HelpCloseButton">&amp;Close</String>
<String Id="InstallLicenseLinkText">[WixBundleName] &lt;a href="#"&gt;license terms&lt;/a&gt;.</String>
<String Id="InstallAcceptCheckbox">I &amp;agree to the license terms and conditions</String>
<String Id="InstallOptionsButton">&amp;Options</String>
<String Id="InstallInstallButton">&amp;Install</String>
<String Id="InstallCloseButton">&amp;Close</String>
<String Id="OptionsHeader">Setup Options</String>
<String Id="OptionsLocationLabel">Install location:</String>
<String Id="OptionsBrowseButton">&amp;Browse</String>
<String Id="OptionsOkButton">&amp;OK</String>
<String Id="OptionsCancelButton">&amp;Cancel</String>
<String Id="ProgressHeader">Setup Progress</String>
<String Id="ProgressLabel">Processing:</String>
<String Id="OverallProgressPackageText">Initializing...</String>
<String Id="ProgressCancelButton">&amp;Cancel</String>
<String Id="ModifyHeader">Modify Setup</String>
<String Id="ModifyRepairButton">&amp;Repair</String>
<String Id="ModifyUninstallButton">&amp;Uninstall</String>
<String Id="ModifyCloseButton">&amp;Close</String>
<String Id="SuccessRepairHeader">Repair Successfully Completed</String>
<String Id="SuccessUninstallHeader">Uninstall Successfully Completed</String>
<String Id="SuccessInstallHeader">Installation Successfully Completed</String>
<String Id="SuccessHeader">Setup Successful</String>
<String Id="SuccessLaunchButton">&amp;Launch</String>
<String Id="SuccessRestartText">You must restart your computer before you can use the software.</String>
<String Id="SuccessRestartButton">&amp;Restart</String>
<String Id="SuccessCloseButton">&amp;Close</String>
<String Id="FailureHeader">Setup Failed</String>
<String Id="FailureInstallHeader">Setup Failed</String>
<String Id="FailureUninstallHeader">Uninstall Failed</String>
<String Id="FailureRepairHeader">Repair Failed</String>
<String Id="FailureHyperlinkLogText">One or more issues caused the setup to fail. Please fix the issues and then retry setup. For more information see the &lt;a href="#"&gt;log file&lt;/a&gt;.</String>
<String Id="FailureRestartText">You must restart your computer to complete the rollback of the software.</String>
<String Id="FailureRestartButton">&amp;Restart</String>
<String Id="FailureCloseButton">&amp;Close</String>
<String Id="FilesInUseHeader">Files In Use</String>
<String Id="FilesInUseLabel">The following applications are using files that need to be updated:</String>
<String Id="FilesInUseCloseRadioButton">Close the &amp;applications and attempt to restart them.</String>
<String Id="FilesInUseDontCloseRadioButton">&amp;Do not close applications. A reboot will be required.</String>
<String Id="FilesInUseOkButton">&amp;OK</String>
<String Id="FilesInUseCancelButton">&amp;Cancel</String>
<String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String>
</WixLocalization>
-91
View File
@@ -1,91 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
<!-- adjusted theme based on https://github.com/wixtoolset/wix3/blob/master/src/ext/BalExtension/wixstdba/Resources/HyperlinkSidebarTheme.xml -->
<Theme xmlns="http://wixtoolset.org/schemas/thmutil/2010">
<Window Width="600" Height="450" HexStyle="100a0000" FontId="0">#(loc.Caption)</Window>
<Font Id="0" Height="-12" Weight="500" Foreground="000000" Background="FFFFFF">Segoe UI</Font>
<Font Id="1" Height="-24" Weight="500" Foreground="000000">Segoe UI</Font>
<Font Id="2" Height="-22" Weight="500" Foreground="666666">Segoe UI</Font>
<Font Id="3" Height="-12" Weight="500" Foreground="000000" Background="FFFFFF">Segoe UI</Font>
<Font Id="4" Height="-12" Weight="500" Foreground="ff0000" Background="FFFFFF" Underline="yes">Segoe UI</Font>
<Font Id="5" Height="-12" Weight="700" Foreground="000000" Background="FFFFFF">Segoe UI</Font>
<Image X="11" Y="11" Width="64" Height="64" ImageFile="logo.png" />
<Text X="80" Y="11" Width="-11" Height="64" FontId="1" DisablePrefix="yes">#(loc.Title)</Text>
<Page Name="Help">
<Image X="11" Y="11" Width="64" Height="64" ImageFile="logo.png" />
<Text X="80" Y="11" Width="-11" Height="64" FontId="1" DisablePrefix="yes">#(loc.Title)</Text>
<Text X="11" Y="80" Width="-11" Height="30" FontId="2" DisablePrefix="yes">#(loc.HelpHeader)</Text>
<Text X="11" Y="112" Width="-11" Height="-35" FontId="3" DisablePrefix="yes">#(loc.HelpText)</Text>
<Button Name="HelpCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.HelpCloseButton)</Button>
</Page>
<Page Name="Install">
<Text X="185" Y="11" Width="-11" Height="32" FontId="1" DisablePrefix="yes">#(loc.Title)</Text>
<Image X="11" Y="11" Width="165" Height="400" ImageFile="logoside.png"/>
<Text X="185" Y="50" Width="-11" Height="32" FontId="2" DisablePrefix="yes">#(loc.InstallHeader)</Text>
<Text X="185" Y="91" Width="-11" Height="64" FontId="3" DisablePrefix="yes">#(loc.InstallMessage)</Text>
<Richedit Name="EulaRichedit" X="185" Y="131" Width="-12" Height="-65" HexStyle="0x00800000" TabStop="yes" FontId="0" />
<Checkbox Name="EulaAcceptCheckbox" X="185" Y="-46" Width="-11" Height="17" TabStop="yes" FontId="3" HideWhenDisabled="yes">#(loc.InstallAcceptCheckbox)</Checkbox>
<Text Name="InstallVersion" X="185" Y="-11" Width="-11" Height="17" FontId="3" DisablePrefix="yes" HideWhenDisabled="yes">#(loc.InstallVersion)</Text>
<Button Name="InstallButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.InstallInstallButton)</Button>
<Button Name="WelcomeCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.InstallCloseButton)</Button>
</Page>
<Page Name="FilesInUse">
<Image X="11" Y="11" Width="64" Height="64" ImageFile="logo.png" />
<Text X="80" Y="11" Width="-11" Height="64" FontId="1" DisablePrefix="yes">#(loc.Title)</Text>
<Text X="11" Y="80" Width="-11" Height="30" FontId="2" DisablePrefix="yes">#(loc.FilesInUseHeader)</Text>
<Text X="11" Y="121" Width="-11" Height="34" FontId="3" DisablePrefix="yes">#(loc.FilesInUseLabel)</Text>
<Text Name="FilesInUseText" X="11" Y="150" Width="-11" Height="-86" FontId="3" DisablePrefix="yes" HexStyle="0x0000000C">A</Text>
<Button Name="FilesInUseCloseRadioButton" X="11" Y="-60" Width="-11" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes" HexStyle="0x000009">#(loc.FilesInUseCloseRadioButton)</Button>
<Button Name="FilesInUseDontCloseRadioButton" X="11" Y="-40" Width="-11" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes" HexStyle="0x000009">#(loc.FilesInUseDontCloseRadioButton)</Button>
<Button Name="FilesInUseOkButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.FilesInUseOkButton)</Button>
<Button Name="FilesInUseCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.FilesInUseCancelButton)</Button>
</Page>
<Page Name="Progress">
<Text X="80" Y="11" Width="-11" Height="32" FontId="1" DisablePrefix="yes">#(loc.Title)</Text>
<Image X="11" Y="11" Width="64" Height="64" ImageFile="logo.png"/>
<Text X="11" Y="80" Width="-11" Height="30" FontId="2" DisablePrefix="yes">#(loc.ProgressHeader)</Text>
<Text X="11" Y="141" Width="70" Height="17" FontId="3" DisablePrefix="yes">#(loc.ProgressLabel)</Text>
<Text Name="OverallProgressPackageText" X="85" Y="141" Width="-11" Height="17" FontId="3" DisablePrefix="yes">#(loc.OverallProgressPackageText)</Text>
<Progressbar Name="OverallCalculatedProgressbar" X="11" Y="163" Width="-11" Height="20" />
<Button Name="ProgressCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.ProgressCancelButton)</Button>
</Page>
<Page Name="Modify">
<Image X="11" Y="11" Width="64" Height="64" ImageFile="logo.png" />
<Text X="80" Y="11" Width="-11" Height="64" FontId="1" DisablePrefix="yes">#(loc.Title)</Text>
<Text X="11" Y="80" Width="-11" Height="30" FontId="2" DisablePrefix="yes">#(loc.ModifyHeader)</Text>
<Button Name="RepairButton" X="-171" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.ModifyRepairButton)</Button>
<Button Name="UninstallButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.ModifyUninstallButton)</Button>
<Button Name="ModifyCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.ModifyCloseButton)</Button>
</Page>
<Page Name="Success">
<Text X="185" Y="11" Width="-11" Height="32" FontId="1" DisablePrefix="yes">#(loc.Title)</Text>
<Image X="11" Y="11" Width="165" Height="400" ImageFile="logoside.png"/>
<Text Name="SuccessHeader" X="185" Y="50" Width="-11" Height="30" FontId="2" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.SuccessHeader)</Text>
<Text Name="SuccessInstallHeader" X="185" Y="50" Width="-11" Height="100" FontId="2" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.SuccessInstallHeader)</Text>
<Text Name="SuccessRepairHeader" X="185" Y="50" Width="-11" Height="100" FontId="2" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.SuccessRepairHeader)</Text>
<Text Name="SuccessUninstallHeader" X="185" Y="50" Width="-11" Height="30" FontId="2" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.SuccessUninstallHeader)</Text>
<Button Name="LaunchButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.SuccessLaunchButton)</Button>
<Text Name="SuccessRestartText" X="185" Y="-51" Width="400" Height="34" FontId="3" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.SuccessRestartText)</Text>
<Button Name="SuccessRestartButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.SuccessRestartButton)</Button>
<Button Name="SuccessCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.SuccessCloseButton)</Button>
</Page>
<Page Name="Failure">
<Text X="185" Y="11" Width="-11" Height="32" FontId="1" DisablePrefix="yes">#(loc.Title)</Text>
<Image X="11" Y="11" Width="165" Height="400" ImageFile="logoside.png"/>
<Text Name="FailureHeader" X="185" Y="50" Width="-11" Height="30" FontId="2" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.FailureHeader)</Text>
<Text Name="FailureInstallHeader" X="185" Y="50" Width="-11" Height="30" FontId="2" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.FailureInstallHeader)</Text>
<Text Name="FailureUninstallHeader" X="185" Y="50" Width="-11" Height="30" FontId="2" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.FailureUninstallHeader)</Text>
<Text Name="FailureRepairHeader" X="185" Y="50" Width="-11" Height="30" FontId="2" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.FailureRepairHeader)</Text>
<Hypertext Name="FailureLogFileLink" X="185" Y="121" Width="-11" Height="68" FontId="3" TabStop="yes" HideWhenDisabled="yes">#(loc.FailureHyperlinkLogText)</Hypertext>
<Hypertext Name="FailureMessageText" X="185" Y="-80" Width="-11" Height="140" FontId="5" TabStop="yes" HideWhenDisabled="yes" />
<Text Name="FailureRestartText" X="185" Y="-57" Width="-11" Height="80" FontId="3" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.FailureRestartText)</Text>
<Button Name="FailureRestartButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.FailureRestartButton)</Button>
<Button Name="FailureCloseButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.FailureCloseButton)</Button>
</Page>
</Theme>
+68
View File
@@ -0,0 +1,68 @@
<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
<WixLocalization Culture="en-us" Language="1033" xmlns="http://wixtoolset.org/schemas/v4/wxl">
<String Id="Caption" Value="[WixBundleName] Setup" />
<String Id="Title" Value="[WixBundleName]" />
<String Id="InstallHeader" Value="Welcome" />
<String Id="InstallMessage" Value="Setup will install [WixBundleName] on your computer." />
<String Id="InstallVersion" Value="Version [WixBundleVersion]" />
<String Id="CheckingForUpdatesLabel" Value="Checking for updates" />
<String Id="UpdateButton" Value="&amp;Update to version [WixStdBAUpdateAvailable]" />
<String Id="InstallVersion" Value="Version [WixBundleVersion]" />
<String Id="ConfirmCancelMessage" Value="Are you sure you want to cancel?" />
<String Id="ExecuteUpgradeRelatedBundleMessage" Value="Previous version" />
<String Id="HelpHeader" Value="Setup Help" />
<String Id="HelpText" Value="/install | /repair | /uninstall | /layout [directory] - installs, repairs, uninstalls or&#xA; creates a complete local copy of the bundle in directory. Install is the default.&#xA;&#xA;/passive | /quiet - displays minimal UI with no prompts or displays no UI and&#xA; no prompts. By default UI and all prompts are displayed.&#xA;&#xA;/norestart - suppress any attempts to restart. By default UI will prompt before restart.&#xA;/log log.txt - logs to a specific file. By default a log file is created in %TEMP%." />
<String Id="HelpCloseButton" Value="&amp;Close" />
<String Id="InstallAcceptCheckbox" Value="I &amp;agree to the license terms and conditions" />
<String Id="InstallOptionsButton" Value="&amp;Options" />
<String Id="InstallInstallButton" Value="&amp;Install" />
<String Id="InstallCancelButton" Value="&amp;Cancel" />
<String Id="OptionsHeader" Value="Setup Options" />
<String Id="OptionsLocationLabel" Value="Install location:" />
<String Id="OptionsBrowseButton" Value="&amp;Browse" />
<String Id="OptionsOkButton" Value="&amp;OK" />
<String Id="OptionsCancelButton" Value="&amp;Cancel" />
<String Id="ProgressHeader" Value="Setup Progress" />
<String Id="ProgressLabel" Value="Processing:" />
<String Id="OverallProgressPackageText" Value="Initializing..." />
<String Id="ProgressCancelButton" Value="&amp;Cancel" />
<String Id="ModifyHeader" Value="Modify Setup" />
<String Id="ModifyRepairButton" Value="&amp;Repair" />
<String Id="ModifyUninstallButton" Value="&amp;Uninstall" />
<String Id="ModifyCancelButton" Value="&amp;Cancel" />
<String Id="SuccessHeader" Value="Setup Successful" />
<String Id="SuccessCacheHeader" Value="Cache Successfully Completed" />
<String Id="SuccessInstallHeader" Value="Installation Successfully Completed" />
<String Id="SuccessLayoutHeader" Value="Layout Successfully Completed" />
<String Id="SuccessModifyHeader" Value="Modify Successfully Completed" />
<String Id="SuccessRepairHeader" Value="Repair Successfully Completed" />
<String Id="SuccessUninstallHeader" Value="Uninstall Successfully Completed" />
<String Id="SuccessUnsafeUninstallHeader" Value="Uninstall Successfully Completed" />
<String Id="SuccessLaunchButton" Value="&amp;Launch" />
<String Id="SuccessRestartText" Value="You must restart your computer before you can use the software." />
<String Id="SuccessUninstallRestartText" Value="You must restart your computer to complete the removal of the software." />
<String Id="SuccessRestartButton" Value="&amp;Restart" />
<String Id="SuccessCloseButton" Value="&amp;Close" />
<String Id="FailureHeader" Value="Setup Failed" />
<String Id="FailureCacheHeader" Value="Cache Failed" />
<String Id="FailureInstallHeader" Value="Setup Failed" />
<String Id="FailureLayoutHeader" Value="Layout Failed" />
<String Id="FailureModifyHeader" Value="Modify Failed" />
<String Id="FailureRepairHeader" Value="Repair Failed" />
<String Id="FailureUninstallHeader" Value="Uninstall Failed" />
<String Id="FailureUnsafeUninstallHeader" Value="Uninstall Failed" />
<String Id="FailureHyperlinkLogText" Value="One or more issues caused the setup to fail. Please fix the issues and then retry setup. For more information see the &lt;a href=&quot;#&quot;&gt;log file&lt;/a&gt;." />
<String Id="FailureRestartText" Value="You must restart your computer to complete the rollback of the software." />
<String Id="FailureRestartButton" Value="&amp;Restart" />
<String Id="FailureCloseButton" Value="&amp;Close" />
<String Id="FilesInUseTitle" Value="Files In Use" />
<String Id="FilesInUseLabel" Value="The following applications are using files that need to be updated:" />
<String Id="FilesInUseNetfxCloseRadioButton" Value="Close the &amp;applications." />
<String Id="FilesInUseCloseRadioButton" Value="Close the &amp;applications and attempt to restart them." />
<String Id="FilesInUseDontCloseRadioButton" Value="&amp;Do not close applications. A reboot will be required." />
<String Id="FilesInUseRetryButton" Value="&amp;Retry" />
<String Id="FilesInUseIgnoreButton" Value="&amp;Ignore" />
<String Id="FilesInUseExitButton" Value="E&amp;xit" />
</WixLocalization>
+133
View File
@@ -0,0 +1,133 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
<Theme xmlns="http://wixtoolset.org/schemas/v4/thmutil">
<Font Id="0" Height="-12" Weight="500" Foreground="windowtext" Background="window">Segoe UI</Font>
<Font Id="1" Height="-24" Weight="500" Foreground="windowtext">Segoe UI</Font>
<Font Id="2" Height="-22" Weight="500" Foreground="graytext">Segoe UI</Font>
<Font Id="3" Height="-12" Weight="500" Foreground="windowtext" Background="window">Segoe UI</Font>
<Window Width="600" Height="450" HexStyle="100a0000" FontId="0" Caption="#(loc.Caption)" IconFile="Cryptobot.ico">
<Page Name="Help">
<Label X="80" Y="11" Width="-11" Height="32" FontId="1" DisablePrefix="yes">#(loc.Title)</Label>
<ImageControl X="11" Y="11" Width="64" Height="64" ImageFile="logo.png"/>
<Label X="11" Y="80" Width="-11" Height="32" FontId="2" DisablePrefix="yes">#(loc.HelpHeader)</Label>
<Label X="11" Y="121" Width="-11" Height="-35" FontId="3" DisablePrefix="yes">#(loc.HelpText)</Label>
<Button Name="HelpCloseButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">
<Text>#(loc.HelpCloseButton)</Text>
<CloseWindowAction />
</Button>
</Page>
<Page Name="Loading">
<Label X="185" Y="50" Width="-11" Height="30" FontId="2" DisablePrefix="yes" Visible="no" Name="CheckingForUpdatesLabel" />
</Page>
<Page Name="Install">
<ImageControl X="11" Y="11" Width="165" Height="400" ImageFile="logoside.png"/>
<Label X="185" Y="11" Width="-11" Height="32" FontId="2" DisablePrefix="yes">#(loc.InstallHeader)</Label>
<Label X="185" Y="50" Width="-11" Height="64" FontId="3" DisablePrefix="yes">
<Text Condition="WixStdBASuppressOptionsUI">#(loc.InstallMessage)</Text>
<Text Condition="NOT WixStdBASuppressOptionsUI">#(loc.InstallMessageOptions)</Text>
</Label>
<Richedit Name="EulaRichedit" X="185" Y="91" Width="-12" Height="-64" HexStyle="0x00800000" TabStop="yes" FontId="0" />
<Checkbox Name="EulaAcceptCheckbox" X="185" Y="-39" Width="-11" Height="17" TabStop="yes" FontId="3" HideWhenDisabled="yes">#(loc.InstallAcceptCheckbox)</Checkbox>
<Label Name="InstallVersion" X="11" Y="-11" Width="165" Height="17" FontId="3" DisablePrefix="yes" VisibleCondition="WixStdBAShowVersion">#(loc.InstallVersion)</Label>
<Button Name="InstallUpdateButton" X="11" Y="-11" Width="200" Height="23" TabStop="yes" FontId="0" EnableCondition="WixStdBAUpdateAvailable" HideWhenDisabled="yes">#(loc.UpdateButton)</Button>
<Button Name="OptionsButton" X="-171" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" VisibleCondition="NOT WixStdBASuppressOptionsUI">
<Text>#(loc.InstallOptionsButton)</Text>
<ChangePageAction Page="Options" />
</Button>
<Button Name="InstallButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.InstallInstallButton)</Button>
<Button Name="InstallCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">
<Text>#(loc.InstallCancelButton)</Text>
<CloseWindowAction />
</Button>
</Page>
<Page Name="Options">
<Label X="80" Y="11" Width="-11" Height="32" FontId="1" DisablePrefix="yes">#(loc.Title)</Label>
<ImageControl X="11" Y="11" Width="64" Height="64" ImageFile="logo.png"/>
<Label X="11" Y="80" Width="-11" Height="30" FontId="2" DisablePrefix="yes">#(loc.OptionsHeader)</Label>
<Label X="11" Y="121" Width="-11" Height="17" FontId="3">#(loc.OptionsLocationLabel)</Label>
<Editbox Name="InstallFolder" X="11" Y="143" Width="-91" Height="21" TabStop="yes" FontId="3" FileSystemAutoComplete="yes" />
<Button Name="BrowseButton" X="-11" Y="142" Width="75" Height="23" TabStop="yes" FontId="3">
<Text>#(loc.OptionsBrowseButton)</Text>
<BrowseDirectoryAction VariableName="InstallFolder" />
</Button>
<Button Name="OptionsOkButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">
<Text>#(loc.OptionsOkButton)</Text>
<ChangePageAction Page="Install" />
</Button>
<Button Name="OptionsCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">
<Text>#(loc.OptionsCancelButton)</Text>
<ChangePageAction Page="Install" Cancel="yes" />
</Button>
</Page>
<Page Name="Progress">
<Label X="80" Y="11" Width="-11" Height="32" FontId="1" DisablePrefix="yes">#(loc.Title)</Label>
<ImageControl X="11" Y="11" Width="64" Height="64" ImageFile="logo.png"/>
<Label X="11" Y="80" Width="-11" Height="30" FontId="2" DisablePrefix="yes">#(loc.ProgressHeader)</Label>
<Label X="11" Y="141" Width="70" Height="17" FontId="3" DisablePrefix="yes">#(loc.ProgressLabel)</Label>
<Label Name="OverallProgressPackageText" X="85" Y="141" Width="-11" Height="17" FontId="3" DisablePrefix="yes">#(loc.OverallProgressPackageText)</Label>
<Progressbar Name="OverallCalculatedProgressbar" X="11" Y="163" Width="-11" Height="20" />
<Button Name="ProgressCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.ProgressCancelButton)</Button>
</Page>
<Page Name="Modify">
<ImageControl X="11" Y="11" Width="165" Height="400" ImageFile="logoside.png"/>
<Label X="185" Y="11" Width="-11" Height="32" FontId="2" DisablePrefix="yes">#(loc.ModifyHeader)</Label>
<Label Name="InstallVersion" X="11" Y="-11" Width="-11" Height="17" FontId="3" DisablePrefix="yes" VisibleCondition="WixStdBAShowVersion">#(loc.InstallVersion)</Label>
<Button Name="ModifyUpdateButton" X="11" Y="-11" Width="200" Height="23" TabStop="yes" FontId="0" EnableCondition="WixStdBAUpdateAvailable" HideWhenDisabled="yes">#(loc.UpdateButton)</Button>
<Button Name="RepairButton" X="-171" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.ModifyRepairButton)</Button>
<Button Name="UninstallButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.ModifyUninstallButton)</Button>
<Button Name="ModifyCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">
<Text>#(loc.ModifyCancelButton)</Text>
<CloseWindowAction />
</Button>
</Page>
<Page Name="Success">
<ImageControl X="11" Y="11" Width="165" Height="400" ImageFile="logoside.png"/>
<Label X="185" Y="11" Width="-11" Height="32" FontId="2" DisablePrefix="yes">
<Text>#(loc.SuccessHeader)</Text>
<Text Condition="WixBundleAction = 2">#(loc.SuccessLayoutHeader)</Text>
<Text Condition="WixBundleAction = 3">#(loc.SuccessUnsafeUninstallHeader)</Text>
<Text Condition="WixBundleAction = 4">#(loc.SuccessUninstallHeader)</Text>
<Text Condition="WixBundleAction = 5">#(loc.SuccessCacheHeader)</Text>
<Text Condition="WixBundleAction = 6">#(loc.SuccessInstallHeader)</Text>
<Text Condition="WixBundleAction = 7">#(loc.SuccessModifyHeader)</Text>
<Text Condition="WixBundleAction = 8">#(loc.SuccessRepairHeader)</Text>
</Label>
<Button Name="LaunchButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.SuccessLaunchButton)</Button>
<Label X="185" Y="-51" Width="400" Height="34" FontId="3" DisablePrefix="yes" VisibleCondition="WixStdBARestartRequired">
<Text>#(loc.SuccessRestartText)</Text>
<Text Condition="WixBundleAction = 3">#(loc.SuccessUninstallRestartText)</Text>
</Label>
<Label Name="InstallVersion" X="11" Y="-11" Width="165" Height="17" FontId="3" DisablePrefix="yes" VisibleCondition="WixStdBAShowVersion">#(loc.InstallVersion)</Label>
<Button Name="SuccessRestartButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.SuccessRestartButton)</Button>
<Button Name="SuccessCloseButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">
<Text>#(loc.SuccessCloseButton)</Text>
<CloseWindowAction />
</Button>
</Page>
<Page Name="Failure">
<ImageControl X="11" Y="11" Width="165" Height="400" ImageFile="logoside.png"/>
<Label X="185" Y="11" Width="-11" Height="32" FontId="2" DisablePrefix="yes">
<Text>#(loc.FailureHeader)</Text>
<Text Condition="WixBundleAction = 2">#(loc.FailureLayoutHeader)</Text>
<Text Condition="WixBundleAction = 3">#(loc.FailureUnsafeUninstallHeader)</Text>
<Text Condition="WixBundleAction = 4">#(loc.FailureUninstallHeader)</Text>
<Text Condition="WixBundleAction = 5">#(loc.FailureCacheHeader)</Text>
<Text Condition="WixBundleAction = 6">#(loc.FailureInstallHeader)</Text>
<Text Condition="WixBundleAction = 7">#(loc.FailureModifyHeader)</Text>
<Text Condition="WixBundleAction = 8">#(loc.FailureRepairHeader)</Text>
</Label>
<Hypertext Name="FailureLogFileLink" X="185" Y="121" Width="-11" Height="68" FontId="3" TabStop="yes" HideWhenDisabled="yes">#(loc.FailureHyperlinkLogText)</Hypertext>
<Hypertext Name="FailureMessageText" X="185" Y="-115" Width="-11" Height="80" FontId="3" TabStop="yes" HideWhenDisabled="yes" />
<Label Name="InstallVersion" X="11" Y="-11" Width="165" Height="17" FontId="3" DisablePrefix="yes" VisibleCondition="WixStdBAShowVersion">#(loc.InstallVersion)</Label>
<Label X="185" Y="-57" Width="-11" Height="80" FontId="3" DisablePrefix="yes" VisibleCondition="WixStdBARestartRequired">#(loc.FailureRestartText)</Label>
<Button Name="FailureRestartButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.FailureRestartButton)</Button>
<Button Name="FailureCloseButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">
<Text>#(loc.FailureCloseButton)</Text>
<CloseWindowAction />
</Button>
</Page>
</Window>
</Theme>
+3 -2
View File
@@ -6,9 +6,10 @@ java ^
-Dcryptomator.ipcSocketPath="~/AppData/Roaming/Cryptomator/ipc.socket" ^ -Dcryptomator.ipcSocketPath="~/AppData/Roaming/Cryptomator/ipc.socket" ^
-Dcryptomator.logDir="~/AppData/Roaming/Cryptomator" ^ -Dcryptomator.logDir="~/AppData/Roaming/Cryptomator" ^
-Dcryptomator.mountPointsDir="~/Cryptomator" ^ -Dcryptomator.mountPointsDir="~/Cryptomator" ^
-Dcryptomator.keychainPath="~/AppData/Roaming/Cryptomator/keychain.json" ^ -Dcryptomator.integrationsWin.keychainPaths="~/AppData/Roaming/Cryptomator/keychain.json" ^
-Dcryptomator.integrationsWin.windowsHelloKeychainPaths="~/AppData/Roaming/Cryptomator/windowsHelloKeychain.json" ^
-Xss20m ^ -Xss20m ^
-Xmx512m ^ -Xmx512m ^
--enable-preview ` --enable-preview `
--enable-native-access=org.cryptomator.jfuse.win ` --enable-native-access=org.cryptomator.jfuse.win `
-m org.cryptomator.desktop/org.cryptomator.launcher.Cryptomator -m org.cryptomator.desktop/org.cryptomator.launcher.Cryptomator
-109
View File
@@ -1,109 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Include>
<Fragment>
<!-- copy pasta from https://github.com/wixtoolset/wix3/blob/develop/src/ext/UIExtension/wixlib/WixUI_InstallDir.wxs with custom exit dialog-->
<UI Id="CustomWizard">
<TextStyle Id="WixUI_Font_Normal" FaceName="Tahoma" Size="8" />
<TextStyle Id="WixUI_Font_Bigger" FaceName="Tahoma" Size="12" />
<TextStyle Id="WixUI_Font_Title" FaceName="Tahoma" Size="9" Bold="yes" />
<Property Id="DefaultUIFont" Value="WixUI_Font_Normal" />
<Property Id="WixUI_Mode" Value="InstallDir" />
<DialogRef Id="BrowseDlg" />
<DialogRef Id="DiskCostDlg" />
<DialogRef Id="ErrorDlg" />
<DialogRef Id="FilesInUse" />
<DialogRef Id="MsiRMFilesInUse" />
<DialogRef Id="PrepareDlg" />
<DialogRef Id="ProgressDlg" />
<DialogRef Id="ResumeDlg" />
<DialogRef Id="UserExit" />
<Publish Dialog="BrowseDlg" Control="OK" Event="DoAction" Value="WixUIValidatePath" Order="3">1</Publish>
<Publish Dialog="BrowseDlg" Control="OK" Event="SpawnDialog" Value="InvalidDirDlg" Order="4"><![CDATA[NOT WIXUI_DONTVALIDATEPATH AND WIXUI_INSTALLDIR_VALID<>"1"]]></Publish>
<!-- custom end dialogs -->
<Publish Dialog="MyExitDialog" Control="Finish" Event="EndDialog" Value="Return" Order="999">1</Publish>
<Publish Dialog="MyFatalErrorDlg" Control="Finish" Event="EndDialog" Value="Return" Order="998">1</Publish>
<Publish Dialog="WelcomeDlg" Control="Next" Event="NewDialog" Value="LicenseAgreementDlg">NOT Installed</Publish>
<Publish Dialog="WelcomeDlg" Control="Next" Event="NewDialog" Value="VerifyReadyDlg">Installed AND PATCH</Publish>
<Publish Dialog="LicenseAgreementDlg" Control="Back" Event="NewDialog" Value="WelcomeDlg">1</Publish>
<Publish Dialog="LicenseAgreementDlg" Control="Next" Event="NewDialog" Value="InstallDirDlg">LicenseAccepted = "1"</Publish>
<Publish Dialog="InstallDirDlg" Control="Back" Event="NewDialog" Value="LicenseAgreementDlg">1</Publish>
<Publish Dialog="InstallDirDlg" Control="Next" Event="SetTargetPath" Value="[WIXUI_INSTALLDIR]" Order="1">1</Publish>
<Publish Dialog="InstallDirDlg" Control="Next" Event="DoAction" Value="WixUIValidatePath" Order="2">NOT WIXUI_DONTVALIDATEPATH</Publish>
<Publish Dialog="InstallDirDlg" Control="Next" Event="SpawnDialog" Value="InvalidDirDlg" Order="3"><![CDATA[NOT WIXUI_DONTVALIDATEPATH AND WIXUI_INSTALLDIR_VALID<>"1"]]></Publish>
<Publish Dialog="InstallDirDlg" Control="Next" Event="NewDialog" Value="VerifyReadyDlg" Order="4">WIXUI_DONTVALIDATEPATH OR WIXUI_INSTALLDIR_VALID="1"</Publish>
<Publish Dialog="InstallDirDlg" Control="ChangeFolder" Property="_BrowseProperty" Value="[WIXUI_INSTALLDIR]" Order="1">1</Publish>
<Publish Dialog="InstallDirDlg" Control="ChangeFolder" Event="SpawnDialog" Value="BrowseDlg" Order="2">1</Publish>
<Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="InstallDirDlg" Order="1">NOT Installed</Publish>
<Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="MaintenanceTypeDlg" Order="2">Installed AND NOT PATCH</Publish>
<Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="WelcomeDlg" Order="2">Installed AND PATCH</Publish>
<Publish Dialog="MaintenanceWelcomeDlg" Control="Next" Event="NewDialog" Value="MaintenanceTypeDlg">1</Publish>
<Publish Dialog="MaintenanceTypeDlg" Control="RepairButton" Event="NewDialog" Value="VerifyReadyDlg">1</Publish>
<Publish Dialog="MaintenanceTypeDlg" Control="RemoveButton" Event="NewDialog" Value="VerifyReadyDlg">1</Publish>
<Publish Dialog="MaintenanceTypeDlg" Control="Back" Event="NewDialog" Value="MaintenanceWelcomeDlg">1</Publish>
<Property Id="ARPNOMODIFY" Value="1" />
<!-- copy pasta from https://github.com/wixtoolset/wix3/blob/develop/src/ext/UIExtension/wixlib/ExitDialog.wxs with adjustments-->
<Dialog Id="MyExitDialog" Width="370" Height="270" Title="!(loc.ExitDialog_Title)">
<Control Id="Finish" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Cancel="yes" Text="!(loc.WixUIFinish)" />
<Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Disabled="yes" Text="!(loc.WixUICancel)" />
<Control Id="Bitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="234" TabSkip="no" Text="!(loc.ExitDialogBitmap)" />
<Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Disabled="yes" Text="!(loc.WixUIBack)" />
<Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" />
<Control Id="Description" Type="Text" X="135" Y="70" Width="220" Height="40" Transparent="yes" NoPrefix="yes" Text="!(loc.ExitDialogDescription)" />
<Control Id="Title" Type="Text" X="135" Y="20" Width="220" Height="60" Transparent="yes" NoPrefix="yes" Text="!(loc.ExitDialogTitle)" />
<!-- TODO: localize? -->
<Control Id="Suggestion" Type="Text" X="135" Y="100" Width="220" Height="60" Transparent="yes" NoPrefix="yes">
<Text>We recommend for the best user experience to download and install the following third party Windows driver:</Text>
</Control>
<Control Id="WinFsp" Type="Hyperlink" X="140" Y="125" Width="220" Height="60" Transparent="yes">
<Text><![CDATA[WinFsp (<a href="https://winfsp.dev/">Homepage</a>)]]></Text>
</Control>
</Dialog>
<!-- copy pasta from https://github.com/wixtoolset/wix3/blob/develop/src/ext/UIExtension/wixlib/FatalError.wxs with adjustments-->
<Dialog Id="MyFatalErrorDlg" Width="370" Height="270" Title="!(loc.FatalError_Title)">
<Control Id="Finish" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Cancel="yes" Text="!(loc.WixUIFinish)">
<Publish Event="EndDialog" Value="Exit">1</Publish>
</Control>
<Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Disabled="yes" Text="!(loc.WixUICancel)" />
<Control Id="Bitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="234" TabSkip="no" Text="!(loc.FatalErrorBitmap)" />
<Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Disabled="yes" Text="!(loc.WixUIBack)" />
<Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" />
<Control Id="Title" Type="Text" X="135" Y="20" Width="220" Height="60" Transparent="yes" NoPrefix="yes" Text="!(loc.FatalErrorTitle)" />
<Control Id="Description" Type="Text" X="135" Y="70" Width="220" Height="80" Transparent="yes" NoPrefix="yes" Text="!(loc.FatalErrorDescription1) !(loc.FatalErrorDescription2)" />
<Control Id="DescriptionReason1" Type="Text" X="135" Y="160" Width="220" Height="20" Transparent="yes" NoPrefix="yes" Hidden="yes" >
<Text>Reason:</Text>
<Condition Action="show">FOUNDRUNNINGAPP</Condition>
</Control>
<Control Id="DescriptionReason2" Type="Text" X="135" Y="170" Width="220" Height="40" Transparent="yes" NoPrefix="yes" Hidden="yes" >
<Text>Application to update was still running during installation.</Text>
<Condition Action="show">FOUNDRUNNINGAPP</Condition>
</Control>
</Dialog>
<InstallUISequence>
<Show Dialog="MyExitDialog" Overridable="yes" OnExit="success"/>
<Show Dialog="MyFatalErrorDlg" Overridable="yes" OnExit="error"/>
</InstallUISequence>
<AdminUISequence>
<Show Dialog="MyExitDialog" Overridable="yes" OnExit="success"/>
<Show Dialog="MyFatalErrorDlg" Overridable="yes" OnExit="error"/>
</AdminUISequence>
</UI>
<UIRef Id="WixUI_Common" />
</Fragment>
</Include>
+105 -115
View File
@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" <ns0:Wix xmlns:ns0="http://wixtoolset.org/schemas/v4/wxs" xmlns:util="http://wixtoolset.org/schemas/v4/wxs/util" >
xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
<?ifdef JpIsSystemWide ?> <?ifdef JpIsSystemWide ?>
<?define JpInstallScope="perMachine"?> <?define JpInstallScope="perMachine"?>
@@ -30,174 +29,165 @@
<?include $(var.JpConfigDir)/overrides.wxi ?> <?include $(var.JpConfigDir)/overrides.wxi ?>
<Product <ns0:Package
Id="$(var.JpProductCode)" Name="$(var.JpAppName)"
Name="$(var.JpAppName)" Language="$(var.JpProductLanguage)"
Language="$(var.JpProductLanguage)" Version="$(var.JpAppVersion)"
Version="$(var.JpAppVersion)" Manufacturer="$(var.JpAppVendor)"
Manufacturer="$(var.JpAppVendor)" UpgradeCode="$(var.JpProductUpgradeCode)"
UpgradeCode="$(var.JpProductUpgradeCode)"> InstallerVersion="$(var.JpInstallerVersion)"
Compressed="$(var.JpCompressedMsi)"
ProductCode="$(var.JpProductCode)"
Scope="$(var.JpInstallScope)">
<Package <ns0:SummaryInformation Manufacturer="$(var.JpAppVendor)" Description="$(var.JpAppDescription)"/>
Description="$(var.JpAppDescription)" <ns0:Media Id="1" Cabinet="Data.cab" EmbedCab="yes" />
Manufacturer="$(var.JpAppVendor)"
InstallerVersion="$(var.JpInstallerVersion)"
Compressed="$(var.JpCompressedMsi)"
InstallScope="$(var.JpInstallScope)" Platform="x64"
/>
<Media Id="1" Cabinet="Data.cab" EmbedCab="yes" />
<Upgrade Id="$(var.JpProductUpgradeCode)"> <ns0:Upgrade Id="$(var.JpProductUpgradeCode)">
<UpgradeVersion <ns0:UpgradeVersion
OnlyDetect="$(var.JpUpgradeVersionOnlyDetectUpgrade)" OnlyDetect="$(var.JpUpgradeVersionOnlyDetectUpgrade)"
Property="JP_UPGRADABLE_FOUND" Property="JP_UPGRADABLE_FOUND"
Maximum="$(var.JpAppVersion)" Maximum="$(var.JpAppVersion)"
MigrateFeatures="yes" MigrateFeatures="yes"
IncludeMaximum="yes" /> <!-- TODO: check if this needs to be set to yes--> IncludeMaximum="$(var.JpUpgradeVersionOnlyDetectUpgrade)"/> <!-- TODO in earlier versions, this was set to yes-->
<UpgradeVersion <ns0:UpgradeVersion
OnlyDetect="$(var.JpUpgradeVersionOnlyDetectDowngrade)" OnlyDetect="$(var.JpUpgradeVersionOnlyDetectDowngrade)"
Property="JP_DOWNGRADABLE_FOUND" Property="JP_DOWNGRADABLE_FOUND"
Minimum="$(var.JpAppVersion)" Minimum="$(var.JpAppVersion)"
MigrateFeatures="yes" MigrateFeatures="yes"
IncludeMinimum="$(var.JpUpgradeVersionOnlyDetectDowngrade)" /> IncludeMinimum="$(var.JpUpgradeVersionOnlyDetectDowngrade)" />
</Upgrade> </ns0:Upgrade>
<?ifndef JpAllowUpgrades ?> <?ifndef JpAllowUpgrades ?>
<CustomAction Id="JpDisallowUpgrade" Error="!(loc.DisallowUpgradeErrorMessage)" /> <ns0:CustomAction Id="JpDisallowUpgrade" Error="!(loc.DisallowUpgradeErrorMessage)" />
<?endif?> <?endif?>
<?ifndef JpAllowDowngrades ?> <?ifndef JpAllowDowngrades ?>
<CustomAction Id="JpDisallowDowngrade" Error="!(loc.DowngradeErrorMessage)" /> <ns0:CustomAction Id="JpDisallowDowngrade" Error="!(loc.DowngradeErrorMessage)" />
<?endif?> <?endif?>
<Binary Id="JpCaDll" SourceFile="$(env.JP_WIXHELPER_DIR)\wixhelper.dll"/> <!-- TODO: how does this work again? -->
<CustomAction Id="JpFindRelatedProducts" BinaryKey="JpCaDll" DllEntry="FindRelatedProductsEx" /> <ns0:Binary Id="JpCaDll" SourceFile="$(env.JP_WIXHELPER_DIR)\wixhelper.dll" />
<ns0:CustomAction Id="JpFindRelatedProducts" BinaryRef="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"> <ns0:Property Id="OLDEXEINSTALLER">
<RegistrySearch Id="InnoSetupInstallation" Root="HKLM" Key="Software\Microsoft\Windows\CurrentVersion\Uninstall\Cryptomator_is1" Type="raw" Name="DisplayName" /> <ns0:RegistrySearch Id="InnoSetupInstallation" Root="HKLM" Key="Software\Microsoft\Windows\CurrentVersion\Uninstall\Cryptomator_is1" Type="raw" Name="DisplayName" />
</Property> </ns0:Property>
<!-- TODO: localize --> <!-- TODO: localize -->
<Condition Message="A lower version of [ProductName] is already installed. Uninstall it first and then start the setup again. Setup will now exit."> <ns0:Launch Message="A lower version of [ProductName] is already installed. Uninstall it first and then start the setup again. Setup will now exit." Condition="Installed OR NOT OLDEXEINSTALLER" />
<![CDATA[Installed OR NOT OLDEXEINSTALLER]]>
</Condition>
<?endif?> <?endif?>
<!-- Cryptomator uses UNIX Sockets, which are supported starting with Windows 10 v1803--> <!-- Cryptomator uses UNIX Sockets, which are supported starting with Windows 10 v1803-->
<Property Id="WINDOWSBUILDNUMBER" Secure="yes"> <ns0:Property Id="WINDOWSBUILDNUMBER" Secure="yes">
<RegistrySearch Id="BuildNumberSearch" Root="HKLM" Key="SOFTWARE\Microsoft\Windows NT\CurrentVersion" Name="CurrentBuildNumber" Type="raw" /> <ns0:RegistrySearch Id="BuildNumberSearch" Root="HKLM" Key="SOFTWARE\Microsoft\Windows NT\CurrentVersion" Name="CurrentBuildNumber" Type="raw" />
</Property> </ns0:Property>
<Condition Message="This application requires Windows 10 version 1803 (build 17134) or newer."> <ns0:Launch Message="This application requires Windows 10 version 1803 (build 17134) or newer." Condition="Installed OR (WINDOWSBUILDNUMBER >= 17134)" />
<![CDATA[Installed OR (WINDOWSBUILDNUMBER >= 17134)]]>
</Condition>
<!-- Non-Opening ProgID --> <!-- Non-Opening ProgID -->
<DirectoryRef Id="INSTALLDIR"> <ns0:DirectoryRef Id="INSTALLDIR">
<Component Win64="yes" Id="nonStartingProgID" > <ns0:Component Bitness="always64" Id="nonStartingProgID" >
<File Id="IconFileForEncryptedData" KeyPath="yes" Source="$(env.JP_WIXWIZARD_RESOURCES)\$(var.IconFileEncryptedData)" Name="$(var.IconFileEncryptedData)"></File> <ns0:File Id="IconFileForEncryptedData" KeyPath="yes" Source="$(env.JP_WIXWIZARD_RESOURCES)\$(var.IconFileEncryptedData)" Name="$(var.IconFileEncryptedData)"/>
<ProgId Id="$(var.JpAppName).Encrypted.1" Description="$(var.JpAppName) Encrypted Data" Icon="IconFileForEncryptedData" IconIndex="0"> <ns0:ProgId Id="$(var.JpAppName).Encrypted.1" Description="$(var.JpAppName) Encrypted Data" Icon="IconFileForEncryptedData" IconIndex="0">
<Extension Id="c9r" Advertise="no" ContentType="$(var.ProgIdContentType)"> <ns0:Extension Id="c9r" Advertise="no" ContentType="$(var.ProgIdContentType)">
<MIME ContentType="$(var.ProgIdContentType)" Default="yes"></MIME> <ns0:MIME ContentType="$(var.ProgIdContentType)" Default="yes"/>
</Extension> </ns0:Extension>
<Extension Id="c9s" Advertise="no" ContentType="$(var.ProgIdContentType)"/> <ns0:Extension Id="c9s" Advertise="no" ContentType="$(var.ProgIdContentType)"/>
</ProgId> </ns0:ProgId>
</Component> </ns0:Component>
</DirectoryRef> </ns0:DirectoryRef>
<!-- Standard required root --> <!-- Standard required root -->
<Directory Id="TARGETDIR" Name="SourceDir"/>
<Feature Id="DefaultFeature" Title="!(loc.MainFeatureTitle)" Level="1"> <ns0:Feature Id="DefaultFeature" Title="!(loc.MainFeatureTitle)" Level="1">
<ComponentGroupRef Id="Shortcuts"/> <ns0:ComponentGroupRef Id="Shortcuts"/>
<ComponentGroupRef Id="Files"/> <ns0:ComponentGroupRef Id="Files"/>
<ComponentGroupRef Id="FileAssociations"/> <ns0:ComponentGroupRef Id="FileAssociations"/>
<!-- Ref to additional ProgIDs --> <!-- Ref to additional ProgIDs -->
<ComponentRef Id="nonStartingProgID" /> <ns0:ComponentRef Id="nonStartingProgID" />
</Feature> </ns0:Feature>
<CustomAction Id="JpSetARPINSTALLLOCATION" Property="ARPINSTALLLOCATION" Value="[INSTALLDIR]" /> <ns0:CustomAction Id="JpSetARPINSTALLLOCATION" Property="ARPINSTALLLOCATION" Value="[INSTALLDIR]" />
<CustomAction Id="JpSetARPCOMMENTS" Property="ARPCOMMENTS" Value="$(var.JpAppDescription)" /> <ns0:CustomAction Id="JpSetARPCOMMENTS" Property="ARPCOMMENTS" Value="$(var.JpAppDescription)" />
<CustomAction Id="JpSetARPCONTACT" Property="ARPCONTACT" Value="$(var.JpAppVendor)" /> <ns0:CustomAction Id="JpSetARPCONTACT" Property="ARPCONTACT" Value="$(var.JpAppVendor)" />
<CustomAction Id="JpSetARPSIZE" Property="ARPSIZE" Value="$(var.JpAppSizeKb)" /> <ns0:CustomAction Id="JpSetARPSIZE" Property="ARPSIZE" Value="$(var.JpAppSizeKb)" />
<?ifdef JpHelpURL ?> <?ifdef JpHelpURL ?>
<CustomAction Id="JpSetARPHELPLINK" Property="ARPHELPLINK" Value="$(var.JpHelpURL)" /> <ns0:CustomAction Id="JpSetARPHELPLINK" Property="ARPHELPLINK" Value="$(var.JpHelpURL)" />
<?endif?> <?endif?>
<?ifdef JpAboutURL ?> <?ifdef JpAboutURL ?>
<CustomAction Id="JpSetARPURLINFOABOUT" Property="ARPURLINFOABOUT" Value="$(var.JpAboutURL)" /> <ns0:CustomAction Id="JpSetARPURLINFOABOUT" Property="ARPURLINFOABOUT" Value="$(var.JpAboutURL)" />
<?endif?> <?endif?>
<?ifdef JpUpdateURL ?> <?ifdef JpUpdateURL ?>
<CustomAction Id="JpSetARPURLUPDATEINFO" Property="ARPURLUPDATEINFO" Value="$(var.JpUpdateURL)" /> <ns0:CustomAction Id="JpSetARPURLUPDATEINFO" Property="ARPURLUPDATEINFO" Value="$(var.JpUpdateURL)" />
<?endif?> <?endif?>
<Property Id="WixQuietExec64CmdTimeout" Value="20" /> <ns0:Property Id="WixQuietExec64CmdTimeout" Value="20" />
<!-- Note for custom actions: Immediate CAs run BEFORE the files are installed, hence if you depend on installed files, the CAs must be deferred.--> <!-- Note for custom actions: Immediate CAs run BEFORE the files are installed, hence if you depend on installed files, the CAs must be deferred.-->
<!-- WebDAV patches --> <!-- WebDAV patches -->
<SetProperty Id="PatchWebDAV" Value="&quot;[INSTALLDIR]patchWebDAV.bat&quot;" <ns0:SetProperty Id="PatchWebDAV" Value="&quot;[INSTALLDIR]patchWebDAV.bat&quot;" Sequence="execute" Before="PatchWebDAV" />
Sequence="execute" Before="PatchWebDAV" /> <ns0:CustomAction Id="PatchWebDAV" BinaryRef="Wix4UtilCA_$(sys.BUILDARCHSHORT)" DllEntry="WixQuietExec" Execute="deferred" Return="ignore" Impersonate="no"/>
<CustomAction Id="PatchWebDAV" BinaryKey="WixCA" DllEntry="WixQuietExec64" Execute="deferred" Return="ignore" Impersonate="no"/>
<!-- Running App detection and exit --> <!-- Running App detection and exit -->
<Property Id="FOUNDRUNNINGAPP" Admin="yes"/> <ns0:Property Id="FOUNDRUNNINGAPP" Admin="yes"/>
<util:CloseApplication <util:CloseApplication
Target="$(var.CloseApplicationTarget)" Target="$(var.CloseApplicationTarget)"
Id="Close$(var.JpAppName)" Id="Close$(var.JpAppName)"
CloseMessage="no" CloseMessage="no"
RebootPrompt="no" RebootPrompt="no"
PromptToContinue="yes" PromptToContinue="yes"
Description="A running instance of $(var.JpAppName) is found, using files marked for update. Please close it to continue." Description="A running instance of $(var.JpAppName) is found, using files marked for update. Please close it to continue."
Property="FOUNDRUNNINGAPP" Property="FOUNDRUNNINGAPP"
> />
</util:CloseApplication> <ns0:CustomAction Id="FailOnRunningApp" Error="Installation aborted, because files marked for update are used by a running instance of $(var.JpAppName)."/>
<CustomAction Id="FailOnRunningApp" Error="Installation aborted, because files marked for update are used by a running instance of $(var.JpAppName)."/>
<?ifdef JpIcon ?> <?ifdef JpIcon ?>
<Property Id="ARPPRODUCTICON" Value="JpARPPRODUCTICON"/> <ns0:Property Id="ARPPRODUCTICON" Value="JpARPPRODUCTICON"/>
<Icon Id="JpARPPRODUCTICON" SourceFile="$(var.JpIcon)"/> <ns0:Icon Id="JpARPPRODUCTICON" SourceFile="$(var.JpIcon)"/>
<?endif?> <?endif?>
<UIRef Id="JpUI"/> <ns0:UIRef Id="JpUI"/>
<InstallExecuteSequence> <ns0:InstallExecuteSequence>
<Custom Action="JpSetARPINSTALLLOCATION" After="CostFinalize">Not Installed</Custom> <ns0:Custom Action="JpSetARPINSTALLLOCATION" After="CostFinalize" Condition="Not Installed" />
<Custom Action="JpSetARPCOMMENTS" After="CostFinalize">Not Installed</Custom> <ns0:Custom Action="JpSetARPCOMMENTS" After="CostFinalize" Condition="Not Installed" />
<Custom Action="JpSetARPCONTACT" After="CostFinalize">Not Installed</Custom> <ns0:Custom Action="JpSetARPCONTACT" After="CostFinalize" Condition="Not Installed" />
<Custom Action="JpSetARPSIZE" After="CostFinalize">Not Installed</Custom> <ns0:Custom Action="JpSetARPSIZE" After="CostFinalize" Condition="Not Installed" />
<?ifdef JpHelpURL ?> <?ifdef JpHelpURL ?>
<Custom Action="JpSetARPHELPLINK" After="CostFinalize">Not Installed</Custom> <ns0:Custom Action="JpSetARPHELPLINK" After="CostFinalize" Condition="Not Installed" />
<?endif?> <?endif?>
<?ifdef JpAboutURL ?> <?ifdef JpAboutURL ?>
<Custom Action="JpSetARPURLINFOABOUT" After="CostFinalize">Not Installed</Custom> <ns0:Custom Action="JpSetARPURLINFOABOUT" After="CostFinalize" Condition="Not Installed" />
<?endif?> <?endif?>
<?ifdef JpUpdateURL ?> <?ifdef JpUpdateURL ?>
<Custom Action="JpSetARPURLUPDATEINFO" After="CostFinalize">Not Installed</Custom> <ns0:Custom Action="JpSetARPURLUPDATEINFO" After="CostFinalize" Condition="Not Installed" />
<?endif?> <?endif?>
<?ifndef JpAllowUpgrades ?> <?ifndef JpAllowUpgrades ?>
<Custom Action="JpDisallowUpgrade" After="JpFindRelatedProducts">JP_UPGRADABLE_FOUND</Custom> <ns0:Custom Action="JpDisallowUpgrade" After="JpFindRelatedProducts" Condition="JP_UPGRADABLE_FOUND"/>
<?endif?> <?endif?>
<?ifndef JpAllowDowngrades ?> <?ifndef JpAllowDowngrades ?>
<Custom Action="JpDisallowDowngrade" After="JpFindRelatedProducts">JP_DOWNGRADABLE_FOUND</Custom> <ns0:Custom Action="JpDisallowDowngrade" After="JpFindRelatedProducts" Condition="JP_DOWNGRADABLE_FOUND" />
<?endif?> <?endif?>
<Custom Action="JpFindRelatedProducts" After="FindRelatedProducts"/> <ns0: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> <ns0:Custom Action="override Wix4CloseApplications_$(sys.BUILDARCHSHORT)" Before="InstallValidate" />
<Custom Action="FailOnRunningApp" After="WixCloseApplications" >FOUNDRUNNINGAPP</Custom> <ns0:Custom Action="FailOnRunningApp" After="Wix4CloseApplications_$(sys.BUILDARCHSHORT)" Condition="FOUNDRUNNINGAPP" />
<RemoveExistingProducts After="InstallValidate"/> <!-- Moved from CostInitialize, due to WixCloseApplications --> <ns0:RemoveExistingProducts After="InstallValidate"/> <!-- Moved from CostInitialize, due to Wix4CloseApplications_* -->
<!-- Skip action on uninstall -->
<!-- TODO: don't skip action, but remove cryptomator alias from hosts file -->
<ns0:Custom Action="PatchWebDAV" After="InstallFiles" Condition="NOT (Installed AND (NOT REINSTALL) AND (NOT UPGRADINGPRODUCTCODE) AND REMOVE)"/>
</ns0:InstallExecuteSequence>
<Custom Action="PatchWebDAV" After="InstallFiles">NOT Installed OR REINSTALL</Custom> <ns0:InstallUISequence>
</InstallExecuteSequence> <ns0:Custom Action="JpFindRelatedProducts" After="FindRelatedProducts"/>
</ns0:InstallUISequence>
<InstallUISequence> <ns0:WixVariable Id="WixUIBannerBmp" Value="$(env.JP_WIXWIZARD_RESOURCES)\banner.bmp" />
<Custom Action="JpFindRelatedProducts" After="FindRelatedProducts"/> <ns0:WixVariable Id="WixUIDialogBmp" Value="$(env.JP_WIXWIZARD_RESOURCES)\background.bmp" />
</InstallUISequence> </ns0:Package>
</ns0:Wix>
<WixVariable Id="WixUIBannerBmp" Value="$(env.JP_WIXWIZARD_RESOURCES)\banner.bmp" />
<WixVariable Id="WixUIDialogBmp" Value="$(env.JP_WIXWIZARD_RESOURCES)\background.bmp" />
</Product>
</Wix>
+1 -1
View File
@@ -47,4 +47,4 @@ Legacy Installation settings:
- SkipCryptomatorLegacyCheck - SkipCryptomatorLegacyCheck
Should be defined to disable checking for the inno setup installation of Cryptomator and undefined, to enable it. Should be defined to disable checking for the inno setup installation of Cryptomator and undefined, to enable it.
--> -->
<Include/> <ns0:Include xmlns:ns0="http://wixtoolset.org/schemas/v4/wxs"></ns0:Include>
-16
View File
@@ -1,16 +0,0 @@
<?xml version="1.0" ?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
<Fragment>
<Property Id="WIXUI_INSTALLDIR" Value="INSTALLDIR"></Property>
<WixVariable Id="WixUILicenseRtf" Value="$(var.JpLicenseRtf)"></WixVariable>
<UI Id="JpUI">
<UIRef Id="CustomWizard" />
<DialogRef Id="InstallDirNotEmptyDlg"></DialogRef>
<Publish Dialog="ShortcutPromptDlg" Control="Back" Event="NewDialog" Value="InstallDirDlg">1</Publish>
<Publish Dialog="ShortcutPromptDlg" Control="Next" Event="NewDialog" Value="VerifyReadyDlg">1</Publish>
<Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="ShortcutPromptDlg" Order="6">NOT Installed</Publish>
<UIRef Id="CustomWizard" />
</UI>
</Fragment>
<?include $(env.JP_WIXWIZARD_RESOURCES)\customWizard.wxi ?>
</Wix>
+30 -19
View File
@@ -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.16.0</version> <version>1.17.0-SNAPSHOT</version>
<name>Cryptomator Desktop App</name> <name>Cryptomator Desktop App</name>
<organization> <organization>
@@ -26,55 +26,66 @@
<properties> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.jdk.version>23</project.jdk.version> <project.jdk.version>24</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 -->
<!-- remove them, as soon they got modularized or support is dropped (i.e., WebDAV) --> <!-- remove them, as soon they got modularized or support is dropped (i.e., WebDAV) -->
<nonModularGroupIds>org.ow2.asm,org.apache.jackrabbit,org.apache.httpcomponents</nonModularGroupIds> <nonModularGroupIds>org.ow2.asm,org.apache.jackrabbit,org.apache.httpcomponents</nonModularGroupIds>
<!-- cryptomator dependencies --> <!-- cryptomator dependencies -->
<cryptomator.cryptofs.version>2.9.0-beta2</cryptomator.cryptofs.version> <cryptomator.cryptofs.version>2.9.0</cryptomator.cryptofs.version>
<cryptomator.integrations.version>1.5.1</cryptomator.integrations.version> <cryptomator.integrations.version>1.6.0</cryptomator.integrations.version>
<cryptomator.integrations.win.version>1.3.0</cryptomator.integrations.win.version> <cryptomator.integrations.win.version>1.5.0</cryptomator.integrations.win.version>
<cryptomator.integrations.mac.version>1.3.0</cryptomator.integrations.mac.version> <cryptomator.integrations.mac.version>1.4.0</cryptomator.integrations.mac.version>
<cryptomator.integrations.linux.version>1.5.3</cryptomator.integrations.linux.version> <cryptomator.integrations.linux.version>1.6.0</cryptomator.integrations.linux.version>
<cryptomator.fuse.version>5.0.3</cryptomator.fuse.version> <cryptomator.fuse.version>5.0.5</cryptomator.fuse.version>
<cryptomator.webdav.version>2.0.8</cryptomator.webdav.version> <cryptomator.webdav.version>2.0.10</cryptomator.webdav.version>
<!-- 3rd party dependencies --> <!-- 3rd party dependencies -->
<commons-lang3.version>3.17.0</commons-lang3.version> <commons-lang3.version>3.17.0</commons-lang3.version>
<dagger.version>2.55</dagger.version> <dagger.version>2.56.1</dagger.version>
<easybind.version>2.2</easybind.version> <easybind.version>2.2</easybind.version>
<jackson.version>2.18.3</jackson.version> <jackson.version>2.18.3</jackson.version>
<javafx.version>23.0.2</javafx.version> <javafx.version>24.0.1</javafx.version>
<jwt.version>4.5.0</jwt.version> <jwt.version>4.5.0</jwt.version>
<nimbus-jose.version>9.37.3</nimbus-jose.version> <nimbus-jose.version>9.37.3</nimbus-jose.version>
<logback.version>1.5.17</logback.version> <logback.version>1.5.18</logback.version>
<slf4j.version>2.0.17</slf4j.version> <slf4j.version>2.0.17</slf4j.version>
<tinyoauth2.version>0.8.1</tinyoauth2.version> <tinyoauth2.version>0.8.1</tinyoauth2.version>
<zxcvbn.version>1.9.0</zxcvbn.version> <zxcvbn.version>1.9.0</zxcvbn.version>
<!-- test dependencies --> <!-- test dependencies -->
<junit.jupiter.version>5.11.4</junit.jupiter.version> <junit.jupiter.version>5.12.2</junit.jupiter.version>
<mockito.version>5.15.2</mockito.version> <mockito.version>5.17.0</mockito.version>
<hamcrest.version>3.0</hamcrest.version> <hamcrest.version>3.0</hamcrest.version>
<!-- build-time dependencies --> <!-- build-time dependencies -->
<jetbrains.annotations.version>26.0.2</jetbrains.annotations.version> <jetbrains.annotations.version>26.0.2</jetbrains.annotations.version>
<dependency-check.version>12.1.0</dependency-check.version> <dependency-check.version>12.1.1</dependency-check.version>
<jacoco.version>0.8.12</jacoco.version> <jacoco.version>0.8.13</jacoco.version>
<license-generator.version>2.5.0</license-generator.version> <license-generator.version>2.5.0</license-generator.version>
<junit-tree-reporter.version>1.4.0</junit-tree-reporter.version> <junit-tree-reporter.version>1.4.0</junit-tree-reporter.version>
<mvn-compiler.version>3.13.0</mvn-compiler.version> <mvn-compiler.version>3.14.0</mvn-compiler.version>
<mvn-resources.version>3.3.1</mvn-resources.version> <mvn-resources.version>3.3.1</mvn-resources.version>
<mvn-dependency.version>3.8.1</mvn-dependency.version> <mvn-dependency.version>3.8.1</mvn-dependency.version>
<mvn-surefire.version>3.5.2</mvn-surefire.version> <mvn-surefire.version>3.5.3</mvn-surefire.version>
<mvn-jar.version>3.4.2</mvn-jar.version> <mvn-jar.version>3.4.2</mvn-jar.version>
<!-- Property used by surefire to determine jacoco engine --> <!-- Property used by surefire to determine jacoco engine -->
<surefire.jacoco.args></surefire.jacoco.args> <surefire.jacoco.args></surefire.jacoco.args>
</properties> </properties>
<!-- TODO: Remove once webdav version 2.0.11 is released -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>webdav-nio-adapter-servlet</artifactId>
<version>1.2.9</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies> <dependencies>
<!-- Cryptomator Libs --> <!-- Cryptomator Libs -->
<dependency> <dependency>
@@ -347,7 +358,7 @@
<consoleOutputReporter> <consoleOutputReporter>
<disable>true</disable> <disable>true</disable>
</consoleOutputReporter> </consoleOutputReporter>
<argLine>@{surefire.jacoco.args} -javaagent:${org.mockito:mockito-core:jar}</argLine> <argLine>@{surefire.jacoco.args} -javaagent:${org.mockito:mockito-core:jar} --enable-native-access=javafx.graphics</argLine>
<statelessTestsetInfoReporter <statelessTestsetInfoReporter
implementation="org.apache.maven.plugin.surefire.extensions.junit5.JUnit5StatelessTestsetInfoTreeReporter"> implementation="org.apache.maven.plugin.surefire.extensions.junit5.JUnit5StatelessTestsetInfoTreeReporter">
</statelessTestsetInfoReporter> </statelessTestsetInfoReporter>
@@ -23,6 +23,7 @@ public class Environment {
private static final String SETTINGS_PATH_PROP_NAME = "cryptomator.settingsPath"; private static final String SETTINGS_PATH_PROP_NAME = "cryptomator.settingsPath";
private static final String IPC_SOCKET_PATH_PROP_NAME = "cryptomator.ipcSocketPath"; private static final String IPC_SOCKET_PATH_PROP_NAME = "cryptomator.ipcSocketPath";
private static final String KEYCHAIN_PATHS_PROP_NAME = "cryptomator.integrationsWin.keychainPaths"; private static final String KEYCHAIN_PATHS_PROP_NAME = "cryptomator.integrationsWin.keychainPaths";
private static final String WINDOWS_HELLO_KEYCHAIN_PATHS_PROP_NAME = "cryptomator.integrationsWin.windowsHelloKeychainPaths";
private static final String P12_PATH_PROP_NAME = "cryptomator.p12Path"; private static final String P12_PATH_PROP_NAME = "cryptomator.p12Path";
private static final String LOG_DIR_PROP_NAME = "cryptomator.logDir"; private static final String LOG_DIR_PROP_NAME = "cryptomator.logDir";
private static final String LOOPBACK_ALIAS_PROP_NAME = "cryptomator.loopbackAlias"; private static final String LOOPBACK_ALIAS_PROP_NAME = "cryptomator.loopbackAlias";
@@ -45,6 +46,7 @@ public class Environment {
logCryptomatorSystemProperty(SETTINGS_PATH_PROP_NAME); logCryptomatorSystemProperty(SETTINGS_PATH_PROP_NAME);
logCryptomatorSystemProperty(IPC_SOCKET_PATH_PROP_NAME); logCryptomatorSystemProperty(IPC_SOCKET_PATH_PROP_NAME);
logCryptomatorSystemProperty(KEYCHAIN_PATHS_PROP_NAME); logCryptomatorSystemProperty(KEYCHAIN_PATHS_PROP_NAME);
logCryptomatorSystemProperty(WINDOWS_HELLO_KEYCHAIN_PATHS_PROP_NAME);
logCryptomatorSystemProperty(P12_PATH_PROP_NAME); logCryptomatorSystemProperty(P12_PATH_PROP_NAME);
logCryptomatorSystemProperty(LOG_DIR_PROP_NAME); logCryptomatorSystemProperty(LOG_DIR_PROP_NAME);
logCryptomatorSystemProperty(LOOPBACK_ALIAS_PROP_NAME); logCryptomatorSystemProperty(LOOPBACK_ALIAS_PROP_NAME);
@@ -85,6 +87,10 @@ public class Environment {
return getPaths(KEYCHAIN_PATHS_PROP_NAME); return getPaths(KEYCHAIN_PATHS_PROP_NAME);
} }
public Stream<Path> getWindowsHelloKeychainPath() {
return getPaths(WINDOWS_HELLO_KEYCHAIN_PATHS_PROP_NAME);
}
public Stream<Path> getP12Path() { public Stream<Path> getP12Path() {
return getPaths(P12_PATH_PROP_NAME); return getPaths(P12_PATH_PROP_NAME);
} }
@@ -42,25 +42,11 @@ public class KeychainManager implements KeychainAccessProvider {
return result; return result;
} }
@Override
public String displayName() {
return getClass().getName();
}
@Override @Override
public void storePassphrase(String key, String displayName, CharSequence passphrase) throws KeychainAccessException { public void storePassphrase(String key, String displayName, CharSequence passphrase) throws KeychainAccessException {
storePassphrase(key, displayName, passphrase, true);
}
//TODO: remove ignored parameter once the API is fixed
@Override
public void storePassphrase(String key, String displayName, CharSequence passphrase, boolean ignored) throws KeychainAccessException {
try { try {
lock.writeLock().lock(); lock.writeLock().lock();
var kc = getKeychainOrFail(); getKeychainOrFail().storePassphrase(key, displayName, passphrase);
//this is the only keychain actually using the parameter
var usesOSAuth = (kc.getClass().getName().equals("org.cryptomator.macos.keychain.TouchIdKeychainAccess"));
kc.storePassphrase(key, displayName, passphrase, usesOSAuth);
} finally { } finally {
lock.writeLock().unlock(); lock.writeLock().unlock();
} }
@@ -44,7 +44,7 @@ public class Settings {
@Deprecated // to be changed to "whatever is available" eventually @Deprecated // to be changed to "whatever is available" eventually
static final String DEFAULT_KEYCHAIN_PROVIDER = SystemUtils.IS_OS_WINDOWS ? "org.cryptomator.windows.keychain.WindowsProtectedKeychainAccess" : // static final String DEFAULT_KEYCHAIN_PROVIDER = SystemUtils.IS_OS_WINDOWS ? "org.cryptomator.windows.keychain.WindowsProtectedKeychainAccess" : //
SystemUtils.IS_OS_MAC ? "org.cryptomator.macos.keychain.MacSystemKeychainAccess" : // SystemUtils.IS_OS_MAC ? "org.cryptomator.macos.keychain.MacSystemKeychainAccess" : //
"org.cryptomator.linux.keychain.SecretServiceKeychainAccess"; "org.cryptomator.linux.keychain.GnomeKeyringKeychainAccess";
static final String DEFAULT_QUICKACCESS_SERVICE = SystemUtils.IS_OS_WINDOWS ? "org.cryptomator.windows.quickaccess.ExplorerQuickAccessService" : // static final String DEFAULT_QUICKACCESS_SERVICE = SystemUtils.IS_OS_WINDOWS ? "org.cryptomator.windows.quickaccess.ExplorerQuickAccessService" : //
SystemUtils.IS_OS_LINUX ? "org.cryptomator.linux.quickaccess.NautilusBookmarks" : null; SystemUtils.IS_OS_LINUX ? "org.cryptomator.linux.quickaccess.NautilusBookmarks" : null;
@@ -147,6 +147,11 @@ public class Settings {
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
private void migrateLegacySettings(SettingsJson json) { private void migrateLegacySettings(SettingsJson json) {
// migrate renamed keychainAccess
if(this.keychainProvider.getValueSafe().equals("org.cryptomator.linux.SecretServiceKeychainAccess")) {
this.keychainProvider.setValue("org.cryptomator.linux.GnomeKeyringKeychainAccess");
}
// implicit migration of 1.6.x legacy setting "preferredVolumeImpl": // implicit migration of 1.6.x legacy setting "preferredVolumeImpl":
if (this.mountService.get() == null && json.preferredVolumeImpl != null) { if (this.mountService.get() == null && json.preferredVolumeImpl != null) {
this.mountService.set(switch (json.preferredVolumeImpl) { this.mountService.set(switch (json.preferredVolumeImpl) {
@@ -10,7 +10,7 @@ package org.cryptomator.common.vaults;
import org.apache.commons.lang3.SystemUtils; import org.apache.commons.lang3.SystemUtils;
import org.cryptomator.common.Constants; import org.cryptomator.common.Constants;
import org.cryptomator.common.EventMap; import org.cryptomator.event.FileSystemEventAggregator;
import org.cryptomator.common.mount.Mounter; import org.cryptomator.common.mount.Mounter;
import org.cryptomator.common.settings.Settings; import org.cryptomator.common.settings.Settings;
import org.cryptomator.common.settings.VaultSettings; import org.cryptomator.common.settings.VaultSettings;
@@ -78,7 +78,7 @@ public class Vault {
private final ObjectBinding<Mountpoint> mountPoint; private final ObjectBinding<Mountpoint> mountPoint;
private final Mounter mounter; private final Mounter mounter;
private final Settings settings; private final Settings settings;
private final EventMap eventMap; private final FileSystemEventAggregator fileSystemEventAggregator;
private final BooleanProperty showingStats; private final BooleanProperty showingStats;
private final AtomicReference<Mounter.MountHandle> mountHandle = new AtomicReference<>(null); private final AtomicReference<Mounter.MountHandle> mountHandle = new AtomicReference<>(null);
@@ -91,7 +91,7 @@ public class Vault {
@Named("lastKnownException") ObjectProperty<Exception> lastKnownException, // @Named("lastKnownException") ObjectProperty<Exception> lastKnownException, //
VaultStats stats, // VaultStats stats, //
Mounter mounter, Settings settings, // Mounter mounter, Settings settings, //
EventMap eventMap) { FileSystemEventAggregator fileSystemEventAggregator) {
this.vaultSettings = vaultSettings; this.vaultSettings = vaultSettings;
this.configCache = configCache; this.configCache = configCache;
this.cryptoFileSystem = cryptoFileSystem; this.cryptoFileSystem = cryptoFileSystem;
@@ -108,7 +108,7 @@ public class Vault {
this.mountPoint = Bindings.createObjectBinding(this::getMountPoint, state); this.mountPoint = Bindings.createObjectBinding(this::getMountPoint, state);
this.mounter = mounter; this.mounter = mounter;
this.settings = settings; this.settings = settings;
this.eventMap = eventMap; this.fileSystemEventAggregator = fileSystemEventAggregator;
this.showingStats = new SimpleBooleanProperty(false); this.showingStats = new SimpleBooleanProperty(false);
this.quickAccessEntry = new AtomicReference<>(null); this.quickAccessEntry = new AtomicReference<>(null);
} }
@@ -261,10 +261,7 @@ public class Vault {
private void consumeVaultEvent(FilesystemEvent e) { private void consumeVaultEvent(FilesystemEvent e) {
var wrapper = new VaultEvent(this, e); fileSystemEventAggregator.put(this, e);
Platform.runLater(() -> {
eventMap.put(wrapper);
});
} }
// ****************************************************************************** // ******************************************************************************
@@ -9,6 +9,7 @@
package org.cryptomator.common.vaults; package org.cryptomator.common.vaults;
import org.apache.commons.lang3.SystemUtils; import org.apache.commons.lang3.SystemUtils;
import org.cryptomator.common.Constants;
import org.cryptomator.common.settings.Settings; import org.cryptomator.common.settings.Settings;
import org.cryptomator.common.settings.VaultSettings; import org.cryptomator.common.settings.VaultSettings;
import org.cryptomator.cryptofs.CryptoFileSystemProvider; import org.cryptomator.cryptofs.CryptoFileSystemProvider;
@@ -35,6 +36,7 @@ import static org.cryptomator.common.Constants.MASTERKEY_FILENAME;
import static org.cryptomator.common.Constants.VAULTCONFIG_FILENAME; import static org.cryptomator.common.Constants.VAULTCONFIG_FILENAME;
import static org.cryptomator.common.vaults.VaultState.Value.ERROR; import static org.cryptomator.common.vaults.VaultState.Value.ERROR;
import static org.cryptomator.common.vaults.VaultState.Value.LOCKED; import static org.cryptomator.common.vaults.VaultState.Value.LOCKED;
import static org.cryptomator.common.vaults.VaultState.Value.NEEDS_MIGRATION;
@Singleton @Singleton
public class VaultListManager { public class VaultListManager {
@@ -115,13 +117,15 @@ public class VaultListManager {
private Vault create(VaultSettings vaultSettings) { private Vault create(VaultSettings vaultSettings) {
var wrapper = new VaultConfigCache(vaultSettings); var wrapper = new VaultConfigCache(vaultSettings);
try { try {
if (Objects.isNull(vaultSettings.lastKnownKeyLoader.get())) {
var keyIdScheme = wrapper.get().getKeyId().getScheme();
vaultSettings.lastKnownKeyLoader.set(keyIdScheme);
}
var vaultState = determineVaultState(vaultSettings.path.get()); var vaultState = determineVaultState(vaultSettings.path.get());
if (vaultState == LOCKED) { //for legacy reasons: pre v8 vault do not have a config, but they are in the NEEDS_MIGRATION state if (vaultState == LOCKED) { //for legacy reasons: pre v8 vault do not have a config, but they are in the NEEDS_MIGRATION state
wrapper.reloadConfig(); wrapper.reloadConfig();
if (Objects.isNull(vaultSettings.lastKnownKeyLoader.get())) {
var keyIdScheme = wrapper.get().getKeyId().getScheme();
vaultSettings.lastKnownKeyLoader.set(keyIdScheme);
}
} else if (vaultState == NEEDS_MIGRATION) {
vaultSettings.lastKnownKeyLoader.set(Constants.DEFAULT_KEY_ID.toString());
} }
return vaultComponentFactory.create(vaultSettings, wrapper, vaultState, null).vault(); return vaultComponentFactory.create(vaultSettings, wrapper, vaultState, null).vault();
} catch (IOException e) { } catch (IOException e) {
@@ -0,0 +1,8 @@
package org.cryptomator.event;
import org.cryptomator.common.vaults.Vault;
import org.cryptomator.cryptofs.event.FilesystemEvent;
import java.nio.file.Path;
public record FSEventBucket(Vault vault, Path idPath, Class<? extends FilesystemEvent> c) {}
@@ -0,0 +1,5 @@
package org.cryptomator.event;
import org.cryptomator.cryptofs.event.FilesystemEvent;
public record FSEventBucketContent(FilesystemEvent mostRecentEvent, int count) {}
@@ -0,0 +1,107 @@
package org.cryptomator.event;
import org.cryptomator.common.vaults.Vault;
import org.cryptomator.cryptofs.event.BrokenDirFileEvent;
import org.cryptomator.cryptofs.event.BrokenFileNodeEvent;
import org.cryptomator.cryptofs.event.ConflictResolutionFailedEvent;
import org.cryptomator.cryptofs.event.ConflictResolvedEvent;
import org.cryptomator.cryptofs.event.DecryptionFailedEvent;
import org.cryptomator.cryptofs.event.FilesystemEvent;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.nio.file.Path;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* Aggregator for {@link FilesystemEvent}s.
* <p>
* The aggregator groups filesystem events by the vault where the event occurred, an identifying path (clear- or ciphertext) and the event class (aka type).
* A group is called an {@link FSEventBucket}, its {@link FSEventBucketContent} is the most recent event object and a count of how often the event already occurred.
*/
@Singleton
public class FileSystemEventAggregator {
private final ConcurrentHashMap<FSEventBucket, FSEventBucketContent> map;
private final AtomicBoolean hasUpdates;
@Inject
public FileSystemEventAggregator() {
this.map = new ConcurrentHashMap<>();
this.hasUpdates = new AtomicBoolean(false);
}
/**
* Adds the given event to the map. If a bucket for this event already exists, only the count is updated and the event set as the most recent one.
*
* @param v Vault where the event occurred
* @param e Actual {@link FilesystemEvent}
*/
public void put(Vault v, FilesystemEvent e) {
var key = computeKey(v, e);
map.compute(key, (k, val) -> {
if (val == null) {
return new FSEventBucketContent(e, 1);
} else {
return new FSEventBucketContent(e, val.count() + 1);
}
});
hasUpdates.set(true);
}
/**
* Removes an event bucket from the map.
*/
public FSEventBucketContent remove(FSEventBucket key) {
var content = map.remove(key);
hasUpdates.set(true);
return content;
}
/**
* Clears the event map.
*/
public void clear() {
map.clear();
hasUpdates.set(true);
}
public boolean hasMaybeUpdates() {
return hasUpdates.get();
}
/**
* Clones the map entries into a collection.
* <p>
* The collection is first cleared, then all map entries are added in one bulk operation. Cleans the hasUpdates status.
*
* @param target collection which is first cleared and then the EntrySet copied to.
*/
public void cloneTo(Collection<Map.Entry<FSEventBucket, FSEventBucketContent>> target) {
hasUpdates.set(false);
target.clear();
target.addAll(map.entrySet());
}
/**
* Method to compute the identifying key for a given filesystem event
*
* @param v Vault where the event occurred
* @param event Actual {@link FilesystemEvent}
* @return a {@link FSEventBucket} used in the map and lru cache
*/
private static FSEventBucket computeKey(Vault v, FilesystemEvent event) {
var p = switch (event) {
case DecryptionFailedEvent(_, Path ciphertextPath, _) -> ciphertextPath;
case ConflictResolvedEvent(_, _, _, _, Path resolvedCiphertext) -> resolvedCiphertext;
case ConflictResolutionFailedEvent(_, _, Path conflictingCiphertext, _) -> conflictingCiphertext;
case BrokenDirFileEvent(_, Path ciphertext) -> ciphertext;
case BrokenFileNodeEvent(_, _, Path ciphertext) -> ciphertext;
};
return new FSEventBucket(v, p, event.getClass());
}
}
@@ -0,0 +1,185 @@
package org.cryptomator.networking;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.Key;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.KeyStoreSpi;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.LinkedHashSet;
import java.util.concurrent.atomic.AtomicInteger;
public class CombinedKeyStoreSpi extends KeyStoreSpi {
private final KeyStore primary;
private final KeyStore fallback;
public static CombinedKeyStoreSpi create(KeyStore primary, KeyStore fallback) {
checkIfLoaded(primary);
checkIfLoaded(fallback);
return new CombinedKeyStoreSpi(primary, fallback);
}
private static void checkIfLoaded(KeyStore s) {
try {
s.aliases();
} catch (KeyStoreException e) {
throw new IllegalArgumentException("Keystore %s is not loaded.".formatted(s.getType()));
}
}
private CombinedKeyStoreSpi(KeyStore primary, KeyStore fallback) {
this.primary = primary;
this.fallback = fallback;
}
@Override
public Key engineGetKey(String alias, char[] password) throws NoSuchAlgorithmException, UnrecoverableKeyException {
try {
Key key = primary.getKey(alias, password);
if (key == null) {
key = fallback.getKey(alias, password);
}
return key;
} catch (KeyStoreException e) {
throw new IllegalStateException("At least one keystore of [%s, %s] is not initialized.".formatted(primary.getType(), fallback.getType()), e);
}
}
@Override
public Certificate[] engineGetCertificateChain(String alias) {
try {
Certificate[] chain = primary.getCertificateChain(alias);
if (chain == null) {
chain = fallback.getCertificateChain(alias);
}
return chain;
} catch (KeyStoreException e) {
throw new IllegalStateException("At least one keystore of [%s, %s] is not initialized.".formatted(primary.getType(), fallback.getType()), e);
}
}
@Override
public Certificate engineGetCertificate(String alias) {
try {
Certificate cert = primary.getCertificate(alias);
if (cert == null) {
cert = fallback.getCertificate(alias);
}
return cert;
} catch (KeyStoreException e) {
throw new IllegalStateException("At least one keystore of [%s, %s] is not initialized.".formatted(primary.getType(), fallback.getType()), e);
}
}
@Override
public Date engineGetCreationDate(String alias) {
try {
Date date = primary.getCreationDate(alias);
if (date == null) {
date = fallback.getCreationDate(alias);
}
return date;
} catch (KeyStoreException e) {
throw new IllegalStateException("At least one keystore of [%s, %s] is not initialized.".formatted(primary.getType(), fallback.getType()), e);
}
}
@Override
public void engineSetKeyEntry(String alias, Key key, char[] password, Certificate[] chain) throws KeyStoreException {
throw new UnsupportedOperationException("Read-only KeyStore");
}
@Override
public void engineSetKeyEntry(String alias, byte[] key, Certificate[] chain) throws KeyStoreException {
throw new UnsupportedOperationException("Read-only KeyStore");
}
@Override
public void engineSetCertificateEntry(String alias, Certificate cert) throws KeyStoreException {
throw new UnsupportedOperationException("Read-only KeyStore");
}
@Override
public void engineDeleteEntry(String alias) throws KeyStoreException {
throw new UnsupportedOperationException("Read-only KeyStore");
}
@Override
public Enumeration<String> engineAliases() {
var aliases = new LinkedHashSet<String>();
try {
primary.aliases().asIterator().forEachRemaining(aliases::add);
fallback.aliases().asIterator().forEachRemaining(aliases::add);
return Collections.enumeration(aliases);
} catch (KeyStoreException e) {
throw new IllegalStateException("At least one keystore of [%s, %s] is not initialized.".formatted(primary.getType(), fallback.getType()), e);
}
}
@Override
public boolean engineContainsAlias(String alias) {
try {
return primary.containsAlias(alias) || fallback.containsAlias(alias);
} catch (KeyStoreException e) {
throw new IllegalStateException("At least one keystore of [%s, %s] is not initialized.".formatted(primary.getType(), fallback.getType()), e);
}
}
@Override
public int engineSize() {
var aliases = engineAliases();
var i = new AtomicInteger(0);
aliases.asIterator().forEachRemaining(_ -> i.incrementAndGet());
return i.get();
}
@Override
public boolean engineIsKeyEntry(String alias) {
try {
return primary.isKeyEntry(alias) || fallback.isKeyEntry(alias);
} catch (KeyStoreException e) {
throw new IllegalStateException("At least one keystore of [%s, %s] is not initialized.".formatted(primary.getType(), fallback.getType()), e);
}
}
@Override
public boolean engineIsCertificateEntry(String alias) {
try {
return primary.isCertificateEntry(alias) || fallback.isCertificateEntry(alias);
} catch (KeyStoreException e) {
throw new IllegalStateException("At least one keystore of [%s, %s] is not initialized.".formatted(primary.getType(), fallback.getType()), e);
}
}
@Override
public String engineGetCertificateAlias(Certificate cert) {
try {
String alias = primary.getCertificateAlias(cert);
if (alias == null) {
alias = fallback.getCertificateAlias(cert);
}
return alias;
} catch (KeyStoreException e) {
throw new IllegalStateException("At least one keystore of [%s, %s] is not initialized.".formatted(primary.getType(), fallback.getType()), e);
}
}
@Override
public void engineStore(OutputStream stream, char[] password) throws IOException, NoSuchAlgorithmException, CertificateException {
throw new UnsupportedOperationException("Read-only KeyStore");
}
@Override
public void engineLoad(InputStream stream, char[] password) throws IOException, NoSuchAlgorithmException, CertificateException {
// Nothing to do; the real keystores are already loaded.
}
}
@@ -6,6 +6,7 @@ import java.io.IOException;
import java.security.KeyStore; import java.security.KeyStore;
import java.security.KeyStoreException; import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.security.Provider;
import java.security.cert.CertificateException; import java.security.cert.CertificateException;
/** /**
@@ -16,6 +17,16 @@ public class SSLContextWithMacKeychain extends SSLContextDifferentTrustStoreBase
@Override @Override
KeyStore getTruststore() throws KeyStoreException, CertificateException, IOException, NoSuchAlgorithmException { KeyStore getTruststore() throws KeyStoreException, CertificateException, IOException, NoSuchAlgorithmException {
return KeyStore.getInstance("KeychainStore-ROOT"); var userKeyStore = KeyStore.getInstance("KeychainStore");
var systemRootKeyStore = KeyStore.getInstance("KeychainStore-ROOT");
userKeyStore.load(null);
systemRootKeyStore.load(null);
try {
CombinedKeyStoreSpi spi = CombinedKeyStoreSpi.create(userKeyStore, systemRootKeyStore);
Provider dummyProvider = new Provider("CombinedKeyStoreProvider", "1.0", "Provides a combined, read-only KeyStore") {};
return new KeyStore(spi, dummyProvider, "CombinedKeyStoreProvider") {};
} catch (IllegalArgumentException e) {
throw new KeyStoreException(e);
}
} }
} }
@@ -12,6 +12,7 @@ public enum FxmlFile {
CONVERTVAULT_HUBTOPASSWORD_START("/fxml/convertvault_hubtopassword_start.fxml"), // CONVERTVAULT_HUBTOPASSWORD_START("/fxml/convertvault_hubtopassword_start.fxml"), //
CONVERTVAULT_HUBTOPASSWORD_CONVERT("/fxml/convertvault_hubtopassword_convert.fxml"), // CONVERTVAULT_HUBTOPASSWORD_CONVERT("/fxml/convertvault_hubtopassword_convert.fxml"), //
CONVERTVAULT_HUBTOPASSWORD_SUCCESS("/fxml/convertvault_hubtopassword_success.fxml"), // CONVERTVAULT_HUBTOPASSWORD_SUCCESS("/fxml/convertvault_hubtopassword_success.fxml"), //
DECRYPTNAMES("/fxml/decryptnames.fxml"), //
ERROR("/fxml/error.fxml"), // ERROR("/fxml/error.fxml"), //
EVENT_VIEW("/fxml/eventview.fxml"), // EVENT_VIEW("/fxml/eventview.fxml"), //
FORGET_PASSWORD("/fxml/forget_password.fxml"), // FORGET_PASSWORD("/fxml/forget_password.fxml"), //
@@ -0,0 +1,25 @@
package org.cryptomator.ui.decryptname;
import javafx.beans.property.ReadOnlyStringWrapper;
import javafx.beans.value.ObservableValue;
import java.nio.file.Path;
public record CipherAndCleartext(Path ciphertext, String cleartextName) {
public String getCiphertextFilename() {
return ciphertext.getFileName().toString();
}
public ObservableValue<String> ciphertextFilenameProperty() {
return new ReadOnlyStringWrapper(getCiphertextFilename());
}
public String getCleartextName() {
return cleartextName;
}
public ObservableValue<String> cleartextNameProperty() {
return new ReadOnlyStringWrapper(getCleartextName());
}
}
@@ -0,0 +1,233 @@
package org.cryptomator.ui.decryptname;
import org.apache.commons.lang3.SystemUtils;
import org.cryptomator.common.vaults.Vault;
import org.cryptomator.cryptofs.common.Constants;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.controls.FontAwesome5Icon;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import javafx.application.Platform;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ListProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleListProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.fxml.FXML;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.input.Clipboard;
import javafx.scene.input.DataFormat;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyCodeCombination;
import javafx.scene.input.TransferMode;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import java.io.File;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Path;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@DecryptNameScoped
public class DecryptFileNamesViewController implements FxController {
private static final Logger LOG = LoggerFactory.getLogger(DecryptFileNamesViewController.class);
private static final KeyCodeCombination COPY_TO_CLIPBOARD_SHORTCUT = new KeyCodeCombination(KeyCode.C, KeyCodeCombination.SHORTCUT_DOWN);
private static final String COPY_TO_CLIPBOARD_SHORTCUT_STRING_WIN = "CTRL+C";
private static final String COPY_TO_CLIPBOARD_SHORTCUT_STRING_MAC = "⌘C";
private static final String COPY_TO_CLIPBOARD_SHORTCUT_STRING_LINUX = "CTRL+C";
private final ListProperty<CipherAndCleartext> mapping;
private final StringProperty dropZoneText = new SimpleStringProperty();
private final ObjectProperty<FontAwesome5Icon> dropZoneIcon = new SimpleObjectProperty<>();
private final BooleanProperty wrongFilesSelected = new SimpleBooleanProperty(false);
private final Stage window;
private final Vault vault;
private final ResourceBundle resourceBundle;
private final List<Path> initialList;
@FXML
public TableColumn<CipherAndCleartext, String> ciphertextColumn;
@FXML
public TableColumn<CipherAndCleartext, String> cleartextColumn;
@FXML
public TableView<CipherAndCleartext> cipherToCleartextTable;
@Inject
public DecryptFileNamesViewController(@DecryptNameWindow Stage window, @DecryptNameWindow Vault vault, @DecryptNameWindow List<Path> pathsToDecrypt, ResourceBundle resourceBundle) {
this.window = window;
this.vault = vault;
this.resourceBundle = resourceBundle;
this.mapping = new SimpleListProperty<>(FXCollections.observableArrayList());
this.initialList = pathsToDecrypt;
}
@FXML
public void initialize() {
cipherToCleartextTable.setItems(mapping);
cipherToCleartextTable.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY_ALL_COLUMNS);
//DragNDrop
cipherToCleartextTable.setOnDragEntered(event -> {
if (event.getGestureSource() == null && event.getDragboard().hasFiles()) {
cipherToCleartextTable.setItems(FXCollections.emptyObservableList());
}
});
cipherToCleartextTable.setOnDragOver(event -> {
if (event.getGestureSource() == null && event.getDragboard().hasFiles()) {
if (SystemUtils.IS_OS_WINDOWS || SystemUtils.IS_OS_MAC) {
event.acceptTransferModes(TransferMode.LINK);
} else {
event.acceptTransferModes(TransferMode.ANY);
}
}
});
cipherToCleartextTable.setOnDragDropped(event -> {
if (event.getGestureSource() == null && event.getDragboard().hasFiles()) {
checkAndDecrypt(event.getDragboard().getFiles().stream().map(File::toPath).toList());
cipherToCleartextTable.setItems(mapping);
}
});
cipherToCleartextTable.setOnDragExited(_ -> cipherToCleartextTable.setItems(mapping));
//selectionModel and copy-to-clipboard action
cipherToCleartextTable.getSelectionModel().setCellSelectionEnabled(true);
cipherToCleartextTable.setOnKeyPressed(keyEvent -> {
if (COPY_TO_CLIPBOARD_SHORTCUT.match(keyEvent)) {
copySingleCelltoClipboard();
}
});
ciphertextColumn.setCellValueFactory(new PropertyValueFactory<>("ciphertextFilename"));
cleartextColumn.setCellValueFactory(new PropertyValueFactory<>("cleartextName"));
dropZoneText.setValue(resourceBundle.getString("decryptNames.dropZone.message"));
dropZoneIcon.setValue(FontAwesome5Icon.FILE_IMPORT);
wrongFilesSelected.addListener((_, _, areWrongFiles) -> {
if (areWrongFiles) {
CompletableFuture.delayedExecutor(5, TimeUnit.SECONDS, Platform::runLater).execute(() -> {
dropZoneText.setValue(resourceBundle.getString("decryptNames.dropZone.message"));
dropZoneIcon.setValue(FontAwesome5Icon.FILE_IMPORT);
wrongFilesSelected.setValue(false);
});
}
});
if (!initialList.isEmpty()) {
checkAndDecrypt(initialList);
}
}
private void copySingleCelltoClipboard() {
cipherToCleartextTable.getSelectionModel().getSelectedCells().stream().findFirst().ifPresent(tablePosition -> {
var selectedItem = cipherToCleartextTable.getSelectionModel().getSelectedItem();
//TODO: give user feedback, if content is copied -> must be done via a custom cell factory to access the actual table cell!
if (tablePosition.getTableColumn().equals(ciphertextColumn)) {
Clipboard.getSystemClipboard().setContent(Map.of(DataFormat.PLAIN_TEXT, selectedItem.ciphertext().toString()));
} else {
Clipboard.getSystemClipboard().setContent(Map.of(DataFormat.PLAIN_TEXT, selectedItem.cleartextName()));
}
});
}
@FXML
public void selectFiles() {
var fileChooser = new FileChooser();
fileChooser.setTitle(resourceBundle.getString("decryptNames.filePicker.title"));
fileChooser.setSelectedExtensionFilter(new FileChooser.ExtensionFilter(resourceBundle.getString("decryptNames.filePicker.extensionDescription"), List.of("*.c9r")));
fileChooser.setInitialDirectory(vault.getPath().toFile());
var ciphertextNodes = fileChooser.showOpenMultipleDialog(window);
if (ciphertextNodes != null) {
checkAndDecrypt(ciphertextNodes.stream().map(File::toPath).toList());
}
}
private void checkAndDecrypt(List<Path> pathsToDecrypt) {
mapping.clear();
//Assumption: All files are in the same directory
var testPath = pathsToDecrypt.getFirst();
if (!testPath.startsWith(vault.getPath())) {
setDropZoneError(resourceBundle.getString("decryptNames.dropZone.error.foreignFiles").formatted(vault.getDisplayName()));
return;
}
if (pathsToDecrypt.size() == 1 && testPath.endsWith(Constants.DIR_ID_BACKUP_FILE_NAME)) {
setDropZoneError(resourceBundle.getString("decryptNames.dropZone.error.vaultInternalFiles"));
return;
}
try {
var newMapping = pathsToDecrypt.stream().filter(p -> !p.endsWith(Constants.DIR_ID_BACKUP_FILE_NAME)).map(this::getCleartextName).toList();
mapping.addAll(newMapping);
} catch (UncheckedIOException e) {
setDropZoneError(resourceBundle.getString("decryptNames.dropZone.error.generic"));
LOG.info("Failed to decrypt filenames for directory {}", testPath.getParent(), e);
} catch (IllegalArgumentException e) {
setDropZoneError(resourceBundle.getString("decryptNames.dropZone.error.vaultInternalFiles"));
} catch (UnsupportedOperationException e) {
setDropZoneError(resourceBundle.getString("decryptNames.dropZone.error.noDirIdBackup"));
}
}
private void setDropZoneError(String text) {
dropZoneIcon.setValue(FontAwesome5Icon.TIMES);
dropZoneText.setValue(text);
wrongFilesSelected.setValue(true);
}
private CipherAndCleartext getCleartextName(Path ciphertextNode) {
try {
var cleartextName = vault.getCleartextName(ciphertextNode);
return new CipherAndCleartext(ciphertextNode, cleartextName);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
//obvservable getter
public ObservableValue<String> dropZoneTextProperty() {
return dropZoneText;
}
public String getDropZoneText() {
return dropZoneText.get();
}
public ObservableValue<FontAwesome5Icon> dropZoneIconProperty() {
return dropZoneIcon;
}
public FontAwesome5Icon getDropZoneIcon() {
return dropZoneIcon.get();
}
public void clearTable() {
mapping.clear();
}
public void copyTableToClipboard() {
var csv = mapping.stream().map(cipherAndClear -> "\"" + cipherAndClear.ciphertext() + "\", \"" + cipherAndClear.cleartextName() + "\"").collect(Collectors.joining("\n"));
Clipboard.getSystemClipboard().setContent(Map.of(DataFormat.PLAIN_TEXT, csv));
}
public String getCopyToClipboardShortcutString() {
if (SystemUtils.IS_OS_WINDOWS) {
return COPY_TO_CLIPBOARD_SHORTCUT_STRING_WIN;
} else if (SystemUtils.IS_OS_MAC) {
return COPY_TO_CLIPBOARD_SHORTCUT_STRING_MAC;
} else {
return COPY_TO_CLIPBOARD_SHORTCUT_STRING_LINUX;
}
}
}
@@ -0,0 +1,50 @@
package org.cryptomator.ui.decryptname;
import dagger.BindsInstance;
import dagger.Lazy;
import dagger.Subcomponent;
import org.cryptomator.common.vaults.Vault;
import org.cryptomator.common.vaults.VaultState;
import org.cryptomator.ui.common.FxmlFile;
import org.cryptomator.ui.common.FxmlScene;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Named;
import javafx.scene.Scene;
import javafx.stage.Stage;
import java.nio.file.Path;
import java.util.List;
@DecryptNameScoped
@Subcomponent(modules = DecryptNameModule.class)
public interface DecryptNameComponent {
Logger LOG = LoggerFactory.getLogger(DecryptNameComponent.class);
@DecryptNameWindow
Stage window();
@FxmlScene(FxmlFile.DECRYPTNAMES)
Lazy<Scene> decryptNamesView();
@DecryptNameWindow
Vault vault();
default void showDecryptFileNameWindow() {
Stage s = window();
s.setScene(decryptNamesView().get());
s.sizeToScene();
if (vault().isUnlocked()) {
s.show();
} else {
LOG.error("Aborted showing DecryptFileName window: vault state is not {}, but {}.", VaultState.Value.UNLOCKED, vault().getState());
}
}
@Subcomponent.Factory
interface Factory {
DecryptNameComponent create(@BindsInstance @DecryptNameWindow Vault vault, @BindsInstance @Named("windowOwner") Stage owner, @BindsInstance @DecryptNameWindow List<Path> pathsToDecrypt);
}
}
@@ -0,0 +1,59 @@
package org.cryptomator.ui.decryptname;
import dagger.Binds;
import dagger.Module;
import dagger.Provides;
import dagger.multibindings.IntoMap;
import org.cryptomator.common.vaults.Vault;
import org.cryptomator.ui.common.DefaultSceneFactory;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.common.FxControllerKey;
import org.cryptomator.ui.common.FxmlFile;
import org.cryptomator.ui.common.FxmlLoaderFactory;
import org.cryptomator.ui.common.FxmlScene;
import org.cryptomator.ui.common.StageFactory;
import javax.inject.Named;
import javax.inject.Provider;
import javafx.scene.Scene;
import javafx.stage.Modality;
import javafx.stage.Stage;
import java.util.Map;
import java.util.ResourceBundle;
@Module
public abstract class DecryptNameModule {
@Provides
@DecryptNameScoped
@DecryptNameWindow
static Stage provideStage(StageFactory factory, @Named("windowOwner") Stage owner, @DecryptNameWindow Vault vault, ResourceBundle resourceBundle) {
Stage stage = factory.create();
stage.setResizable(true);
stage.initModality(Modality.WINDOW_MODAL);
stage.initOwner(owner);
stage.setTitle(resourceBundle.getString("decryptNames.title"));
vault.stateProperty().addListener(((_, _, _) -> stage.close())); //as soon as the state changes from unlocked, close the window
return stage;
}
@Provides
@DecryptNameScoped
@DecryptNameWindow
static FxmlLoaderFactory provideFxmlLoaderFactory(Map<Class<? extends FxController>, Provider<FxController>> factories, DefaultSceneFactory sceneFactory, ResourceBundle resourceBundle) {
return new FxmlLoaderFactory(factories, sceneFactory, resourceBundle);
}
@Provides
@FxmlScene(FxmlFile.DECRYPTNAMES)
@DecryptNameScoped
static Scene provideDecryptNamesViewScene(@DecryptNameWindow FxmlLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene(FxmlFile.DECRYPTNAMES);
}
@Binds
@IntoMap
@FxControllerKey(DecryptFileNamesViewController.class)
abstract FxController bindDecryptNamesViewController(DecryptFileNamesViewController controller);
}
@@ -0,0 +1,11 @@
package org.cryptomator.ui.decryptname;
import javax.inject.Scope;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Scope
@Documented
@Retention(RetentionPolicy.RUNTIME)
@interface DecryptNameScoped {}
@@ -0,0 +1,12 @@
package org.cryptomator.ui.decryptname;
import javax.inject.Qualifier;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Qualifier
@Documented
@Retention(RUNTIME)
@interface DecryptNameWindow {}
@@ -20,8 +20,8 @@ public interface ErrorComponent {
default Stage show() { default Stage show() {
Stage stage = window(); Stage stage = window();
stage.setScene(scene()); stage.setScene(scene());
stage.setMinWidth(420); stage.setMinWidth(450);
stage.setMinHeight(300); stage.setMinHeight(450);
stage.show(); stage.show();
return stage; return stage;
} }
@@ -1,6 +1,8 @@
package org.cryptomator.ui.eventview; package org.cryptomator.ui.eventview;
import org.cryptomator.common.EventMap; import org.cryptomator.event.FSEventBucket;
import org.cryptomator.event.FSEventBucketContent;
import org.cryptomator.event.FileSystemEventAggregator;
import org.cryptomator.common.Nullable; import org.cryptomator.common.Nullable;
import org.cryptomator.common.ObservableUtil; import org.cryptomator.common.ObservableUtil;
import org.cryptomator.cryptofs.CryptoPath; import org.cryptomator.cryptofs.CryptoPath;
@@ -9,7 +11,6 @@ import org.cryptomator.cryptofs.event.BrokenFileNodeEvent;
import org.cryptomator.cryptofs.event.ConflictResolutionFailedEvent; import org.cryptomator.cryptofs.event.ConflictResolutionFailedEvent;
import org.cryptomator.cryptofs.event.ConflictResolvedEvent; import org.cryptomator.cryptofs.event.ConflictResolvedEvent;
import org.cryptomator.cryptofs.event.DecryptionFailedEvent; import org.cryptomator.cryptofs.event.DecryptionFailedEvent;
import org.cryptomator.event.VaultEvent;
import org.cryptomator.integrations.revealpath.RevealFailedException; import org.cryptomator.integrations.revealpath.RevealFailedException;
import org.cryptomator.integrations.revealpath.RevealPathService; import org.cryptomator.integrations.revealpath.RevealPathService;
import org.cryptomator.ui.common.FxController; import org.cryptomator.ui.common.FxController;
@@ -41,6 +42,7 @@ import java.nio.file.Path;
import java.time.ZoneId; import java.time.ZoneId;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle; import java.time.format.FormatStyle;
import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.ResourceBundle; import java.util.ResourceBundle;
import java.util.function.Function; import java.util.function.Function;
@@ -51,11 +53,11 @@ public class EventListCellController implements FxController {
private static final DateTimeFormatter LOCAL_DATE_FORMATTER = DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT).withZone(ZoneId.systemDefault()); private static final DateTimeFormatter LOCAL_DATE_FORMATTER = DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT).withZone(ZoneId.systemDefault());
private static final DateTimeFormatter LOCAL_TIME_FORMATTER = DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT).withZone(ZoneId.systemDefault()); private static final DateTimeFormatter LOCAL_TIME_FORMATTER = DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT).withZone(ZoneId.systemDefault());
private final EventMap eventMap; private final FileSystemEventAggregator fileSystemEventAggregator;
@Nullable @Nullable
private final RevealPathService revealService; private final RevealPathService revealService;
private final ResourceBundle resourceBundle; private final ResourceBundle resourceBundle;
private final ObjectProperty<VaultEvent> event; private final ObjectProperty<Map.Entry<FSEventBucket, FSEventBucketContent>> eventEntry;
private final StringProperty eventMessage; private final StringProperty eventMessage;
private final StringProperty eventDescription; private final StringProperty eventDescription;
private final ObjectProperty<FontAwesome5Icon> eventIcon; private final ObjectProperty<FontAwesome5Icon> eventIcon;
@@ -77,18 +79,18 @@ public class EventListCellController implements FxController {
Button eventActionsButton; Button eventActionsButton;
@Inject @Inject
public EventListCellController(EventMap eventMap, Optional<RevealPathService> revealService, ResourceBundle resourceBundle) { public EventListCellController(FileSystemEventAggregator fileSystemEventAggregator, Optional<RevealPathService> revealService, ResourceBundle resourceBundle) {
this.eventMap = eventMap; this.fileSystemEventAggregator = fileSystemEventAggregator;
this.revealService = revealService.orElseGet(() -> null); this.revealService = revealService.orElseGet(() -> null);
this.resourceBundle = resourceBundle; this.resourceBundle = resourceBundle;
this.event = new SimpleObjectProperty<>(null); this.eventEntry = new SimpleObjectProperty<>(null);
this.eventMessage = new SimpleStringProperty(); this.eventMessage = new SimpleStringProperty();
this.eventDescription = new SimpleStringProperty(); this.eventDescription = new SimpleStringProperty();
this.eventIcon = new SimpleObjectProperty<>(); this.eventIcon = new SimpleObjectProperty<>();
this.eventCount = ObservableUtil.mapWithDefault(event, e -> e.count() == 1? "" : "("+ e.count() +")", ""); this.eventCount = ObservableUtil.mapWithDefault(eventEntry, e -> e.getValue().count() == 1? "" : "("+ e.getValue().count() +")", "");
this.vaultUnlocked = ObservableUtil.mapWithDefault(event.flatMap(e -> e.v().unlockedProperty()), Function.identity(), false); this.vaultUnlocked = ObservableUtil.mapWithDefault(eventEntry.flatMap(e -> e.getKey().vault().unlockedProperty()), Function.identity(), false);
this.readableTime = ObservableUtil.mapWithDefault(event, e -> LOCAL_TIME_FORMATTER.format(e.actualEvent().getTimestamp()), ""); this.readableTime = ObservableUtil.mapWithDefault(eventEntry, e -> LOCAL_TIME_FORMATTER.format(e.getValue().mostRecentEvent().getTimestamp()), "");
this.readableDate = ObservableUtil.mapWithDefault(event, e -> LOCAL_DATE_FORMATTER.format(e.actualEvent().getTimestamp()), ""); this.readableDate = ObservableUtil.mapWithDefault(eventEntry, e -> LOCAL_DATE_FORMATTER.format(e.getValue().mostRecentEvent().getTimestamp()), "");
this.message = Bindings.createStringBinding(this::selectMessage, vaultUnlocked, eventMessage); this.message = Bindings.createStringBinding(this::selectMessage, vaultUnlocked, eventMessage);
this.description = Bindings.createStringBinding(this::selectDescription, vaultUnlocked, eventDescription); this.description = Bindings.createStringBinding(this::selectDescription, vaultUnlocked, eventDescription);
this.icon = Bindings.createObjectBinding(this::selectIcon, vaultUnlocked, eventIcon); this.icon = Bindings.createObjectBinding(this::selectIcon, vaultUnlocked, eventIcon);
@@ -108,13 +110,15 @@ public class EventListCellController implements FxController {
return vaultUnlocked.getValue() && (eventActionsMenu.isShowing() || root.isHover()); return vaultUnlocked.getValue() && (eventActionsMenu.isShowing() || root.isHover());
} }
public void setEvent(@NotNull VaultEvent item) { public void setEventEntry(@NotNull Map.Entry<FSEventBucket, FSEventBucketContent> item) {
event.set(item); eventEntry.set(item);
eventActionsMenu.hide(); eventActionsMenu.hide();
eventActionsMenu.getItems().clear(); eventActionsMenu.getItems().clear();
eventTooltip.setText(item.v().getDisplayName()); eventTooltip.setText(item.getKey().vault().getDisplayName());
addAction("generic.action.dismiss", () -> eventMap.remove(item)); addAction("generic.action.dismiss", () -> {
switch (item.actualEvent()) { fileSystemEventAggregator.remove(item.getKey());
});
switch (item.getValue().mostRecentEvent()) {
case ConflictResolvedEvent fse -> this.adjustToConflictResolvedEvent(fse); case ConflictResolvedEvent fse -> this.adjustToConflictResolvedEvent(fse);
case ConflictResolutionFailedEvent fse -> this.adjustToConflictEvent(fse); case ConflictResolutionFailedEvent fse -> this.adjustToConflictEvent(fse);
case DecryptionFailedEvent fse -> this.adjustToDecryptionFailedEvent(fse); case DecryptionFailedEvent fse -> this.adjustToDecryptionFailedEvent(fse);
@@ -129,9 +133,9 @@ public class EventListCellController implements FxController {
eventMessage.setValue(resourceBundle.getString("eventView.entry.brokenFileNode.message")); eventMessage.setValue(resourceBundle.getString("eventView.entry.brokenFileNode.message"));
eventDescription.setValue(bfe.ciphertextPath().getFileName().toString()); eventDescription.setValue(bfe.ciphertextPath().getFileName().toString());
if (revealService != null) { if (revealService != null) {
addAction("eventView.entry.brokenFileNode.showEncrypted", () -> reveal(revealService, convertVaultPathToSystemPath(bfe.ciphertextPath()))); addAction("eventView.entry.brokenFileNode.showEncrypted", () -> reveal(revealService, bfe.ciphertextPath()));
} else { } else {
addAction("eventView.entry.brokenFileNode.copyEncrypted", () -> copyToClipboard(convertVaultPathToSystemPath(bfe.ciphertextPath()).toString())); addAction("eventView.entry.brokenFileNode.copyEncrypted", () -> copyToClipboard(bfe.ciphertextPath().toString()));
} }
addAction("eventView.entry.brokenFileNode.copyDecrypted", () -> copyToClipboard(convertVaultPathToSystemPath(bfe.cleartextPath()).toString())); addAction("eventView.entry.brokenFileNode.copyDecrypted", () -> copyToClipboard(convertVaultPathToSystemPath(bfe.cleartextPath()).toString()));
} }
@@ -202,23 +206,25 @@ public class EventListCellController implements FxController {
if (vaultUnlocked.getValue()) { if (vaultUnlocked.getValue()) {
return eventMessage.getValue(); return eventMessage.getValue();
} else { } else {
return resourceBundle.getString("eventView.entry.vaultLocked.message"); return "***********";
} }
} }
private String selectDescription() { private String selectDescription() {
if (vaultUnlocked.getValue()) { if (vaultUnlocked.getValue()) {
return eventDescription.getValue(); return eventDescription.getValue();
} else if (eventEntry.getValue() != null) {
var e = eventEntry.getValue().getKey();
return resourceBundle.getString("eventView.entry.vaultLocked.description").formatted(e != null ? e.vault().getDisplayName() : "");
} else { } else {
var e = event.getValue(); return "";
return resourceBundle.getString("eventView.entry.vaultLocked.description").formatted(e != null ? e.v().getDisplayName() : "");
} }
} }
@FXML @FXML
public void toggleEventActionsMenu() { public void toggleEventActionsMenu() {
var e = event.get(); var e = eventEntry.get();
if (e != null) { if (e != null) {
if (eventActionsMenu.isShowing()) { if (eventActionsMenu.isShowing()) {
eventActionsMenu.hide(); eventActionsMenu.hide();
@@ -232,7 +238,7 @@ public class EventListCellController implements FxController {
if (!(p instanceof CryptoPath)) { if (!(p instanceof CryptoPath)) {
throw new IllegalArgumentException("Path " + p + " is not a vault path"); throw new IllegalArgumentException("Path " + p + " is not a vault path");
} }
var v = event.getValue().v(); var v = eventEntry.getValue().getKey().vault();
if (!v.isUnlocked()) { if (!v.isUnlocked()) {
return Path.of(System.getProperty("user.home")); return Path.of(System.getProperty("user.home"));
} }
@@ -1,6 +1,7 @@
package org.cryptomator.ui.eventview; package org.cryptomator.ui.eventview;
import org.cryptomator.event.VaultEvent; import org.cryptomator.event.FSEventBucket;
import org.cryptomator.event.FSEventBucketContent;
import org.cryptomator.ui.common.FxmlLoaderFactory; import org.cryptomator.ui.common.FxmlLoaderFactory;
import javax.inject.Inject; import javax.inject.Inject;
@@ -12,9 +13,10 @@ import javafx.scene.control.ListView;
import javafx.util.Callback; import javafx.util.Callback;
import java.io.IOException; import java.io.IOException;
import java.io.UncheckedIOException; import java.io.UncheckedIOException;
import java.util.Map;
@EventViewScoped @EventViewScoped
public class EventListCellFactory implements Callback<ListView<VaultEvent>, ListCell<VaultEvent>> { public class EventListCellFactory implements Callback<ListView<Map.Entry<FSEventBucket, FSEventBucketContent>>, ListCell<Map.Entry<FSEventBucket, FSEventBucketContent>>> {
private static final String FXML_PATH = "/fxml/eventview_cell.fxml"; private static final String FXML_PATH = "/fxml/eventview_cell.fxml";
@@ -27,7 +29,7 @@ public class EventListCellFactory implements Callback<ListView<VaultEvent>, List
@Override @Override
public ListCell<VaultEvent> call(ListView<VaultEvent> eventListView) { public ListCell<Map.Entry<FSEventBucket, FSEventBucketContent>> call(ListView<Map.Entry<FSEventBucket, FSEventBucketContent>> eventListView) {
try { try {
FXMLLoader fxmlLoader = fxmlLoaders.load(FXML_PATH); FXMLLoader fxmlLoader = fxmlLoaders.load(FXML_PATH);
return new Cell(fxmlLoader.getRoot(), fxmlLoader.getController()); return new Cell(fxmlLoader.getRoot(), fxmlLoader.getController());
@@ -36,7 +38,7 @@ public class EventListCellFactory implements Callback<ListView<VaultEvent>, List
} }
} }
private static class Cell extends ListCell<VaultEvent> { private static class Cell extends ListCell<Map.Entry<FSEventBucket, FSEventBucketContent>> {
private final Parent root; private final Parent root;
private final EventListCellController controller; private final EventListCellController controller;
@@ -47,7 +49,7 @@ public class EventListCellFactory implements Callback<ListView<VaultEvent>, List
} }
@Override @Override
protected void updateItem(VaultEvent item, boolean empty) { protected void updateItem(Map.Entry<FSEventBucket, FSEventBucketContent> item, boolean empty) {
super.updateItem(item, empty); super.updateItem(item, empty);
if (empty || item == null) { if (empty || item == null) {
@@ -57,7 +59,7 @@ public class EventListCellFactory implements Callback<ListView<VaultEvent>, List
this.getStyleClass().addLast("list-cell"); this.getStyleClass().addLast("list-cell");
setContentDisplay(ContentDisplay.GRAPHIC_ONLY); setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
setGraphic(root); setGraphic(root);
controller.setEvent(item); controller.setEventEntry(item);
} }
} }
} }
@@ -1,15 +1,16 @@
package org.cryptomator.ui.eventview; package org.cryptomator.ui.eventview;
import org.cryptomator.common.EventMap;
import org.cryptomator.common.vaults.Vault; import org.cryptomator.common.vaults.Vault;
import org.cryptomator.event.VaultEvent; import org.cryptomator.event.FSEventBucket;
import org.cryptomator.event.FSEventBucketContent;
import org.cryptomator.event.FileSystemEventAggregator;
import org.cryptomator.ui.common.FxController; import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.fxapp.FxFSEventList;
import javax.inject.Inject; import javax.inject.Inject;
import javafx.beans.value.ObservableValue; import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections; import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener; import javafx.collections.ListChangeListener;
import javafx.collections.MapChangeListener;
import javafx.collections.ObservableList; import javafx.collections.ObservableList;
import javafx.collections.transformation.FilteredList; import javafx.collections.transformation.FilteredList;
import javafx.collections.transformation.SortedList; import javafx.collections.transformation.SortedList;
@@ -17,17 +18,16 @@ import javafx.fxml.FXML;
import javafx.scene.control.ChoiceBox; import javafx.scene.control.ChoiceBox;
import javafx.scene.control.ListView; import javafx.scene.control.ListView;
import javafx.util.StringConverter; import javafx.util.StringConverter;
import java.util.Comparator; import java.util.Map;
import java.util.ResourceBundle; import java.util.ResourceBundle;
@EventViewScoped @EventViewScoped
public class EventViewController implements FxController { public class EventViewController implements FxController {
private final EventMap eventMap; private final FilteredList<Map.Entry<FSEventBucket, FSEventBucketContent>> filteredEventList;
private final ObservableList<VaultEvent> eventList;
private final FilteredList<VaultEvent> filteredEventList;
private final ObservableList<Vault> vaults; private final ObservableList<Vault> vaults;
private final SortedList<VaultEvent> reversedEventList; private final FileSystemEventAggregator aggregator;
private final SortedList<Map.Entry<FSEventBucket, FSEventBucketContent>> sortedEventList;
private final ObservableList<Vault> choiceBoxEntries; private final ObservableList<Vault> choiceBoxEntries;
private final ResourceBundle resourceBundle; private final ResourceBundle resourceBundle;
private final EventListCellFactory cellFactory; private final EventListCellFactory cellFactory;
@@ -35,20 +35,45 @@ public class EventViewController implements FxController {
@FXML @FXML
ChoiceBox<Vault> vaultFilterChoiceBox; ChoiceBox<Vault> vaultFilterChoiceBox;
@FXML @FXML
ListView<VaultEvent> eventListView; ListView<Map.Entry<FSEventBucket, FSEventBucketContent>> eventListView;
@Inject @Inject
public EventViewController(EventMap eventMap, ObservableList<Vault> vaults, ResourceBundle resourceBundle, EventListCellFactory cellFactory) { public EventViewController(FxFSEventList fxFSEventList, ObservableList<Vault> vaults, ResourceBundle resourceBundle, EventListCellFactory cellFactory, FileSystemEventAggregator aggregator) {
this.eventMap = eventMap; this.filteredEventList = fxFSEventList.getObservableList().filtered(_ -> true);
this.eventList = FXCollections.observableArrayList();
this.filteredEventList = eventList.filtered(_ -> true);
this.vaults = vaults; this.vaults = vaults;
this.reversedEventList = new SortedList<>(filteredEventList, Comparator.reverseOrder()); this.aggregator = aggregator;
this.sortedEventList = new SortedList<>(filteredEventList, this::compareBuckets);
this.choiceBoxEntries = FXCollections.observableArrayList(); this.choiceBoxEntries = FXCollections.observableArrayList();
this.resourceBundle = resourceBundle; this.resourceBundle = resourceBundle;
this.cellFactory = cellFactory; this.cellFactory = cellFactory;
} }
/**
* Comparison method for the lru cache. During comparsion the map is accessed.
* First the entries are compared by the event timestamp, then vaultId, then identifying path and lastly by class name.
*
* @param left an entry of a {@link FSEventBucket} and its content
* @param right another entry of a {@link FSEventBucket} plus content, compared to {@code left}
* @return a negative integer, zero, or a positive integer as the first argument is less than, equal to, or greater than the second.
*/
private int compareBuckets(Map.Entry<FSEventBucket, FSEventBucketContent> left, Map.Entry<FSEventBucket, FSEventBucketContent> right) {
var t1 = left.getValue().mostRecentEvent().getTimestamp();
var t2 = right.getValue().mostRecentEvent().getTimestamp();
var timeComparison = t1.compareTo(t2);
if (timeComparison != 0) {
return -timeComparison; //we need the reverse timesorting
}
var vaultIdComparison = left.getKey().vault().getId().compareTo(right.getKey().vault().getId());
if (vaultIdComparison != 0) {
return vaultIdComparison;
}
var pathComparison = left.getKey().idPath().compareTo(right.getKey().idPath());
if (pathComparison != 0) {
return pathComparison;
}
return left.getKey().c().getName().compareTo(right.getKey().c().getName());
}
@FXML @FXML
public void initialize() { public void initialize() {
choiceBoxEntries.add(null); choiceBoxEntries.add(null);
@@ -60,39 +85,25 @@ public class EventViewController implements FxController {
} }
}); });
eventList.addAll(eventMap.values());
eventMap.addListener((MapChangeListener<? super EventMap.EventKey, ? super VaultEvent>) this::updateList);
eventListView.setCellFactory(cellFactory); eventListView.setCellFactory(cellFactory);
eventListView.setItems(reversedEventList); eventListView.setItems(sortedEventList);
vaultFilterChoiceBox.setItems(choiceBoxEntries); vaultFilterChoiceBox.setItems(choiceBoxEntries);
vaultFilterChoiceBox.valueProperty().addListener(this::applyVaultFilter); vaultFilterChoiceBox.valueProperty().addListener(this::applyVaultFilter);
vaultFilterChoiceBox.setConverter(new VaultConverter(resourceBundle)); vaultFilterChoiceBox.setConverter(new VaultConverter(resourceBundle));
} }
private void updateList(MapChangeListener.Change<? extends EventMap.EventKey, ? extends VaultEvent> change) {
if (change.wasAdded() && change.wasRemoved()) {
//entry updated
eventList.remove(change.getValueRemoved());
eventList.addLast(change.getValueAdded());
} else if (change.wasAdded()) {
eventList.addLast(change.getValueAdded());
} else { //removed
eventList.remove(change.getValueRemoved());
}
}
private void applyVaultFilter(ObservableValue<? extends Vault> v, Vault oldV, Vault newV) { private void applyVaultFilter(ObservableValue<? extends Vault> v, Vault oldV, Vault newV) {
if (newV == null) { if (newV == null) {
filteredEventList.setPredicate(_ -> true); filteredEventList.setPredicate(_ -> true);
} else { } else {
filteredEventList.setPredicate(e -> e.v().equals(newV)); filteredEventList.setPredicate(e -> e.getKey().vault().equals(newV));
} }
} }
@FXML @FXML
void clearEvents() { void clearEvents() {
eventMap.clear(); aggregator.clear();
} }
private static class VaultConverter extends StringConverter<Vault> { private static class VaultConverter extends StringConverter<Vault> {
@@ -11,6 +11,7 @@ import org.cryptomator.ui.common.FxmlFile;
import org.cryptomator.ui.common.FxmlLoaderFactory; import org.cryptomator.ui.common.FxmlLoaderFactory;
import org.cryptomator.ui.common.FxmlScene; import org.cryptomator.ui.common.FxmlScene;
import org.cryptomator.ui.common.StageFactory; import org.cryptomator.ui.common.StageFactory;
import org.cryptomator.ui.fxapp.FxFSEventList;
import javax.inject.Provider; import javax.inject.Provider;
import javafx.scene.Scene; import javafx.scene.Scene;
@@ -25,12 +26,17 @@ abstract class EventViewModule {
@Provides @Provides
@EventViewScoped @EventViewScoped
@EventViewWindow @EventViewWindow
static Stage provideStage(StageFactory factory, ResourceBundle resourceBundle) { static Stage provideStage(StageFactory factory, ResourceBundle resourceBundle, FxFSEventList fxFSEventList) {
Stage stage = factory.create(); Stage stage = factory.create();
stage.setHeight(498); stage.setHeight(498);
stage.setTitle(resourceBundle.getString("eventView.title")); stage.setTitle(resourceBundle.getString("eventView.title"));
stage.setResizable(true); stage.setResizable(true);
stage.initModality(Modality.NONE); stage.initModality(Modality.NONE);
stage.focusedProperty().addListener((_,_,isFocused) -> {
if(isFocused) {
fxFSEventList.unreadEventsProperty().setValue(false);
}
});
return stage; return stage;
} }
@@ -29,9 +29,10 @@ public class FxApplication {
private final FxApplicationStyle applicationStyle; private final FxApplicationStyle applicationStyle;
private final FxApplicationTerminator applicationTerminator; private final FxApplicationTerminator applicationTerminator;
private final AutoUnlocker autoUnlocker; private final AutoUnlocker autoUnlocker;
private final FxFSEventList fxFSEventList;
@Inject @Inject
FxApplication(@Named("startupTime") long startupTime, Environment environment, Settings settings, AppLaunchEventHandler launchEventHandler, Lazy<TrayMenuComponent> trayMenu, FxApplicationWindows appWindows, FxApplicationStyle applicationStyle, FxApplicationTerminator applicationTerminator, AutoUnlocker autoUnlocker) { FxApplication(@Named("startupTime") long startupTime, Environment environment, Settings settings, AppLaunchEventHandler launchEventHandler, Lazy<TrayMenuComponent> trayMenu, FxApplicationWindows appWindows, FxApplicationStyle applicationStyle, FxApplicationTerminator applicationTerminator, AutoUnlocker autoUnlocker, FxFSEventList fxFSEventList) {
this.startupTime = startupTime; this.startupTime = startupTime;
this.environment = environment; this.environment = environment;
this.settings = settings; this.settings = settings;
@@ -41,6 +42,7 @@ public class FxApplication {
this.applicationStyle = applicationStyle; this.applicationStyle = applicationStyle;
this.applicationTerminator = applicationTerminator; this.applicationTerminator = applicationTerminator;
this.autoUnlocker = autoUnlocker; this.autoUnlocker = autoUnlocker;
this.fxFSEventList = fxFSEventList;
} }
public void start() { public void start() {
@@ -85,6 +87,7 @@ public class FxApplication {
migrateAndInformDokanyRemoval(); migrateAndInformDokanyRemoval();
launchEventHandler.startHandlingLaunchEvents(); launchEventHandler.startHandlingLaunchEvents();
fxFSEventList.schedulePollForUpdates();
autoUnlocker.tryUnlockForTimespan(2, TimeUnit.MINUTES); autoUnlocker.tryUnlockForTimespan(2, TimeUnit.MINUTES);
} }
@@ -7,6 +7,7 @@ package org.cryptomator.ui.fxapp;
import dagger.Module; import dagger.Module;
import dagger.Provides; import dagger.Provides;
import org.cryptomator.ui.decryptname.DecryptNameComponent;
import org.cryptomator.ui.error.ErrorComponent; import org.cryptomator.ui.error.ErrorComponent;
import org.cryptomator.ui.eventview.EventViewComponent; import org.cryptomator.ui.eventview.EventViewComponent;
import org.cryptomator.ui.health.HealthCheckComponent; import org.cryptomator.ui.health.HealthCheckComponent;
@@ -20,11 +21,15 @@ import org.cryptomator.ui.unlock.UnlockComponent;
import org.cryptomator.ui.updatereminder.UpdateReminderComponent; import org.cryptomator.ui.updatereminder.UpdateReminderComponent;
import org.cryptomator.ui.vaultoptions.VaultOptionsComponent; import org.cryptomator.ui.vaultoptions.VaultOptionsComponent;
import javax.inject.Named;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.scene.image.Image; import javafx.scene.image.Image;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@Module(includes = {UpdateCheckerModule.class}, subcomponents = {TrayMenuComponent.class, // @Module(includes = {UpdateCheckerModule.class}, subcomponents = {TrayMenuComponent.class, //
DecryptNameComponent.class, //
MainWindowComponent.class, // MainWindowComponent.class, //
PreferencesComponent.class, // PreferencesComponent.class, //
VaultOptionsComponent.class, // VaultOptionsComponent.class, //
@@ -0,0 +1,67 @@
package org.cryptomator.ui.fxapp;
import org.cryptomator.event.FSEventBucket;
import org.cryptomator.event.FSEventBucketContent;
import org.cryptomator.event.FileSystemEventAggregator;
import javax.inject.Inject;
import javafx.application.Platform;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import java.util.Map;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* List of all occurred filesystem events.
* <p>
* The list exposes an observable list and a property to listen for updates. Internally it polls the {@link FileSystemEventAggregator} in a regular interval for updates.
* If an update is available, the list from the {@link FileSystemEventAggregator } is cloned to this list on the FX application thread.
*/
@FxApplicationScoped
public class FxFSEventList {
private final ObservableList<Map.Entry<FSEventBucket, FSEventBucketContent>> events;
private final FileSystemEventAggregator eventAggregator;
private final ScheduledExecutorService scheduler;
private final BooleanProperty unreadEvents;
@Inject
public FxFSEventList(FileSystemEventAggregator fsEventAggregator, ScheduledExecutorService scheduler) {
this.events = FXCollections.observableArrayList();
this.eventAggregator = fsEventAggregator;
this.scheduler = scheduler;
this.unreadEvents = new SimpleBooleanProperty(false);
}
public void schedulePollForUpdates() {
scheduler.schedule(this::checkForEventUpdates, 1000, TimeUnit.MILLISECONDS);
}
/**
* Checks for event updates and reschedules.
* If updates are available, the aggregated events are copied from back- to the frontend.
* Reschedules itself on successful execution
*/
private void checkForEventUpdates() {
if (eventAggregator.hasMaybeUpdates()) {
Platform.runLater(() -> {
eventAggregator.cloneTo(events);
unreadEvents.setValue(true);
schedulePollForUpdates();
});
} else {
schedulePollForUpdates();
}
}
public ObservableList<Map.Entry<FSEventBucket, FSEventBucketContent>> getObservableList() {
return events;
}
public BooleanProperty unreadEventsProperty() {
return unreadEvents;
}
}
@@ -36,6 +36,7 @@ import javafx.stage.Stage;
import javafx.stage.WindowEvent; import javafx.stage.WindowEvent;
import javafx.util.Duration; import javafx.util.Duration;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
@PassphraseEntryScoped @PassphraseEntryScoped
public class PassphraseEntryController implements FxController { public class PassphraseEntryController implements FxController {
@@ -49,6 +50,7 @@ public class PassphraseEntryController implements FxController {
private final ForgetPasswordComponent.Builder forgetPassword; private final ForgetPasswordComponent.Builder forgetPassword;
private final KeychainManager keychain; private final KeychainManager keychain;
private final StringBinding vaultName; private final StringBinding vaultName;
private final ExecutorService backgroundExecutorService;
private final BooleanProperty unlockInProgress = new SimpleBooleanProperty(); private final BooleanProperty unlockInProgress = new SimpleBooleanProperty();
private final ObjectBinding<ContentDisplay> unlockButtonContentDisplay = Bindings.when(unlockInProgress).then(ContentDisplay.LEFT).otherwise(ContentDisplay.TEXT_ONLY); private final ObjectBinding<ContentDisplay> unlockButtonContentDisplay = Bindings.when(unlockInProgress).then(ContentDisplay.LEFT).otherwise(ContentDisplay.TEXT_ONLY);
private final BooleanProperty unlockButtonDisabled = new SimpleBooleanProperty(); private final BooleanProperty unlockButtonDisabled = new SimpleBooleanProperty();
@@ -64,7 +66,7 @@ public class PassphraseEntryController implements FxController {
public Animation unlockAnimation; public Animation unlockAnimation;
@Inject @Inject
public PassphraseEntryController(@KeyLoading Stage window, @KeyLoading Vault vault, CompletableFuture<PassphraseEntryResult> result, @Nullable @Named("savedPassword") Passphrase savedPassword, ForgetPasswordComponent.Builder forgetPassword, KeychainManager keychain) { public PassphraseEntryController(@KeyLoading Stage window, @KeyLoading Vault vault, CompletableFuture<PassphraseEntryResult> result, @Nullable @Named("savedPassword") Passphrase savedPassword, ForgetPasswordComponent.Builder forgetPassword, KeychainManager keychain, ExecutorService backgroundExecutorService) {
this.window = window; this.window = window;
this.vault = vault; this.vault = vault;
this.result = result; this.result = result;
@@ -72,8 +74,8 @@ public class PassphraseEntryController implements FxController {
this.forgetPassword = forgetPassword; this.forgetPassword = forgetPassword;
this.keychain = keychain; this.keychain = keychain;
this.vaultName = WeakBindings.bindString(vault.displayNameProperty()); this.vaultName = WeakBindings.bindString(vault.displayNameProperty());
this.backgroundExecutorService = backgroundExecutorService;
window.setOnHiding(this::windowClosed); window.setOnHiding(this::windowClosed);
result.whenCompleteAsync((r, t) -> unlockInProgress.set(false), Platform::runLater);
} }
@FXML @FXML
@@ -119,8 +121,6 @@ public class PassphraseEntryController implements FxController {
new KeyFrame(Duration.millis(800), legsExtendedY, legsExtendedX, faceHidden), // new KeyFrame(Duration.millis(800), legsExtendedY, legsExtendedX, faceHidden), //
new KeyFrame(Duration.millis(1000), faceVisible) // new KeyFrame(Duration.millis(1000), faceVisible) //
); );
result.whenCompleteAsync((r, t) -> stopUnlockAnimation());
} }
@FXML @FXML
@@ -133,6 +133,9 @@ public class PassphraseEntryController implements FxController {
result.cancel(true); result.cancel(true);
LOG.debug("Unlock canceled by user."); LOG.debug("Unlock canceled by user.");
} }
if( passwordField != null) {
passwordField.getCharacters().destroy();
}
} }
@@ -142,7 +145,7 @@ public class PassphraseEntryController implements FxController {
unlockInProgress.set(true); unlockInProgress.set(true);
CharSequence pwFieldContents = passwordField.getCharacters(); CharSequence pwFieldContents = passwordField.getCharacters();
Passphrase pw = Passphrase.copyOf(pwFieldContents); Passphrase pw = Passphrase.copyOf(pwFieldContents);
result.complete(new PassphraseEntryResult(pw, savePasswordCheckbox.isSelected())); result.completeAsync(() -> new PassphraseEntryResult(pw, savePasswordCheckbox.isSelected()), backgroundExecutorService);
startUnlockAnimation(); startUnlockAnimation();
} }
@@ -13,6 +13,7 @@ import org.cryptomator.integrations.revealpath.RevealFailedException;
import org.cryptomator.integrations.revealpath.RevealPathService; import org.cryptomator.integrations.revealpath.RevealPathService;
import org.cryptomator.ui.common.FxController; import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.common.VaultService; import org.cryptomator.ui.common.VaultService;
import org.cryptomator.ui.decryptname.DecryptNameComponent;
import org.cryptomator.ui.fxapp.FxApplicationWindows; import org.cryptomator.ui.fxapp.FxApplicationWindows;
import org.cryptomator.ui.stats.VaultStatisticsComponent; import org.cryptomator.ui.stats.VaultStatisticsComponent;
import org.cryptomator.ui.wrongfilealert.WrongFileAlertComponent; import org.cryptomator.ui.wrongfilealert.WrongFileAlertComponent;
@@ -47,7 +48,6 @@ import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors;
@MainWindowScoped @MainWindowScoped
public class VaultDetailUnlockedController implements FxController { public class VaultDetailUnlockedController implements FxController {
@@ -61,6 +61,7 @@ public class VaultDetailUnlockedController implements FxController {
private final WrongFileAlertComponent.Builder wrongFileAlert; private final WrongFileAlertComponent.Builder wrongFileAlert;
private final Stage mainWindow; private final Stage mainWindow;
private final Optional<RevealPathService> revealPathService; private final Optional<RevealPathService> revealPathService;
private final DecryptNameComponent.Factory decryptNameWindowFactory;
private final ResourceBundle resourceBundle; private final ResourceBundle resourceBundle;
private final LoadingCache<Vault, VaultStatisticsComponent> vaultStats; private final LoadingCache<Vault, VaultStatisticsComponent> vaultStats;
private final VaultStatisticsComponent.Builder vaultStatsBuilder; private final VaultStatisticsComponent.Builder vaultStatsBuilder;
@@ -70,7 +71,6 @@ public class VaultDetailUnlockedController implements FxController {
private final BooleanProperty draggingOverLocateEncrypted = new SimpleBooleanProperty(); private final BooleanProperty draggingOverLocateEncrypted = new SimpleBooleanProperty();
private final BooleanProperty draggingOverDecryptName = new SimpleBooleanProperty(); private final BooleanProperty draggingOverDecryptName = new SimpleBooleanProperty();
private final BooleanProperty ciphertextPathsCopied = new SimpleBooleanProperty(); private final BooleanProperty ciphertextPathsCopied = new SimpleBooleanProperty();
private final BooleanProperty cleartextNamesCopied = new SimpleBooleanProperty();
@FXML @FXML
public Button revealEncryptedDropZone; public Button revealEncryptedDropZone;
@@ -78,13 +78,22 @@ public class VaultDetailUnlockedController implements FxController {
public Button decryptNameDropZone; public Button decryptNameDropZone;
@Inject @Inject
public VaultDetailUnlockedController(ObjectProperty<Vault> vault, FxApplicationWindows appWindows, VaultService vaultService, VaultStatisticsComponent.Builder vaultStatsBuilder, WrongFileAlertComponent.Builder wrongFileAlert, @MainWindow Stage mainWindow, Optional<RevealPathService> revealPathService, ResourceBundle resourceBundle) { public VaultDetailUnlockedController(ObjectProperty<Vault> vault, //
FxApplicationWindows appWindows, //
VaultService vaultService, //
VaultStatisticsComponent.Builder vaultStatsBuilder, //
WrongFileAlertComponent.Builder wrongFileAlert, //
@MainWindow Stage mainWindow, //
Optional<RevealPathService> revealPathService, //
DecryptNameComponent.Factory decryptNameWindowFactory, //
ResourceBundle resourceBundle) {
this.vault = vault; this.vault = vault;
this.appWindows = appWindows; this.appWindows = appWindows;
this.vaultService = vaultService; this.vaultService = vaultService;
this.wrongFileAlert = wrongFileAlert; this.wrongFileAlert = wrongFileAlert;
this.mainWindow = mainWindow; this.mainWindow = mainWindow;
this.revealPathService = revealPathService; this.revealPathService = revealPathService;
this.decryptNameWindowFactory = decryptNameWindowFactory;
this.resourceBundle = resourceBundle; this.resourceBundle = resourceBundle;
this.vaultStats = CacheBuilder.newBuilder().weakValues().build(CacheLoader.from(this::buildVaultStats)); this.vaultStats = CacheBuilder.newBuilder().weakValues().build(CacheLoader.from(this::buildVaultStats));
this.vaultStatsBuilder = vaultStatsBuilder; this.vaultStatsBuilder = vaultStatsBuilder;
@@ -106,7 +115,7 @@ public class VaultDetailUnlockedController implements FxController {
revealEncryptedDropZone.setOnDragExited(_ -> draggingOverLocateEncrypted.setValue(false)); revealEncryptedDropZone.setOnDragExited(_ -> draggingOverLocateEncrypted.setValue(false));
decryptNameDropZone.setOnDragOver(e -> handleDragOver(e, draggingOverDecryptName)); decryptNameDropZone.setOnDragOver(e -> handleDragOver(e, draggingOverDecryptName));
decryptNameDropZone.setOnDragDropped(e -> handleDragDropped(e, this::getCleartextName, this::copyDecryptedNamesToClipboard)); decryptNameDropZone.setOnDragDropped(e -> showDecryptNameWindow(e.getDragboard().getFiles().stream().map(File::toPath).toList()));
decryptNameDropZone.setOnDragExited(_ -> draggingOverDecryptName.setValue(false)); decryptNameDropZone.setOnDragExited(_ -> draggingOverDecryptName.setValue(false));
EasyBind.includeWhen(revealEncryptedDropZone.getStyleClass(), ACTIVE_CLASS, draggingOverLocateEncrypted); EasyBind.includeWhen(revealEncryptedDropZone.getStyleClass(), ACTIVE_CLASS, draggingOverLocateEncrypted);
@@ -153,39 +162,12 @@ public class VaultDetailUnlockedController implements FxController {
} }
@FXML @FXML
public void chooseEncryptedFileAndCopyNames() { public void showDecryptNameWindow() {
var fileChooser = new FileChooser(); showDecryptNameWindow(List.of());
fileChooser.setTitle(resourceBundle.getString("main.vaultDetail.decryptName.filePickerTitle"));
fileChooser.setInitialDirectory(vault.getValue().getPath().toFile());
var ciphertextNode = fileChooser.showOpenDialog(mainWindow);
if (ciphertextNode != null) {
var nodeName = getCleartextName(ciphertextNode.toPath());
copyDecryptedNamesToClipboard(List.of(nodeName));
}
} }
private void copyDecryptedNamesToClipboard(List<CipherToCleartext> mapping) { private void showDecryptNameWindow(List<Path> pathsToDecrypt) {
if (mapping.size() == 1) { decryptNameWindowFactory.create(vault.get(), mainWindow, pathsToDecrypt).showDecryptFileNameWindow();
Clipboard.getSystemClipboard().setContent(Map.of(DataFormat.PLAIN_TEXT, mapping.getFirst().cleartext));
} else {
var content = mapping.stream().map(CipherToCleartext::toString).collect(Collectors.joining("\n"));
Clipboard.getSystemClipboard().setContent(Map.of(DataFormat.PLAIN_TEXT, content));
}
cleartextNamesCopied.setValue(true);
CompletableFuture.delayedExecutor(2, TimeUnit.SECONDS, Platform::runLater).execute(() -> {
cleartextNamesCopied.set(false);
});
}
@Nullable
private CipherToCleartext getCleartextName(Path ciphertextNode) {
try {
return new CipherToCleartext(ciphertextNode.getFileName().toString(), vault.get().getCleartextName(ciphertextNode));
} catch (IOException e) {
LOG.warn("Failed to decrypt filename for {}", ciphertextNode, e);
return null;
}
} }
private boolean startsWithVaultAccessPoint(Path path) { private boolean startsWithVaultAccessPoint(Path path) {
@@ -260,14 +242,6 @@ public class VaultDetailUnlockedController implements FxController {
vaultStats.getUnchecked(vault.get()).showVaultStatisticsWindow(); vaultStats.getUnchecked(vault.get()).showVaultStatisticsWindow();
} }
record CipherToCleartext(String ciphertext, String cleartext) {
@Override
public String toString() {
return ciphertext + " > " + cleartext;
}
}
/* Getter/Setter */ /* Getter/Setter */
public ReadOnlyObjectProperty<Vault> vaultProperty() { public ReadOnlyObjectProperty<Vault> vaultProperty() {
@@ -310,11 +284,5 @@ public class VaultDetailUnlockedController implements FxController {
return ciphertextPathsCopied.get(); return ciphertextPathsCopied.get();
} }
public BooleanProperty cleartextNamesCopiedProperty() {
return cleartextNamesCopied;
}
public boolean isCleartextNamesCopied() {
return cleartextNamesCopied.get();
}
} }
@@ -1,17 +1,16 @@
package org.cryptomator.ui.mainwindow; package org.cryptomator.ui.mainwindow;
import org.apache.commons.lang3.SystemUtils; import org.apache.commons.lang3.SystemUtils;
import org.cryptomator.common.EventMap;
import org.cryptomator.common.settings.Settings; import org.cryptomator.common.settings.Settings;
import org.cryptomator.common.vaults.Vault; import org.cryptomator.common.vaults.Vault;
import org.cryptomator.common.vaults.VaultListManager; import org.cryptomator.common.vaults.VaultListManager;
import org.cryptomator.cryptofs.CryptoFileSystemProvider; import org.cryptomator.cryptofs.CryptoFileSystemProvider;
import org.cryptomator.cryptofs.DirStructure; import org.cryptomator.cryptofs.DirStructure;
import org.cryptomator.event.VaultEvent;
import org.cryptomator.ui.addvaultwizard.AddVaultWizardComponent; import org.cryptomator.ui.addvaultwizard.AddVaultWizardComponent;
import org.cryptomator.ui.common.FxController; import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.common.VaultService; import org.cryptomator.ui.common.VaultService;
import org.cryptomator.ui.dialogs.Dialogs; import org.cryptomator.ui.dialogs.Dialogs;
import org.cryptomator.ui.fxapp.FxFSEventList;
import org.cryptomator.ui.fxapp.FxApplicationWindows; import org.cryptomator.ui.fxapp.FxApplicationWindows;
import org.cryptomator.ui.preferences.SelectedPreferencesTab; import org.cryptomator.ui.preferences.SelectedPreferencesTab;
import org.slf4j.Logger; import org.slf4j.Logger;
@@ -25,7 +24,6 @@ import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.value.ObservableValue; import javafx.beans.value.ObservableValue;
import javafx.collections.ListChangeListener; import javafx.collections.ListChangeListener;
import javafx.collections.MapChangeListener;
import javafx.collections.ObservableList; import javafx.collections.ObservableList;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.geometry.Side; import javafx.geometry.Side;
@@ -69,8 +67,7 @@ public class VaultListController implements FxController {
private final VaultListCellFactory cellFactory; private final VaultListCellFactory cellFactory;
private final AddVaultWizardComponent.Builder addVaultWizard; private final AddVaultWizardComponent.Builder addVaultWizard;
private final BooleanBinding emptyVaultList; private final BooleanBinding emptyVaultList;
private final EventMap eventMap; private final BooleanProperty unreadEvents;
private final BooleanProperty newEventsPresent;
private final VaultListManager vaultListManager; private final VaultListManager vaultListManager;
private final BooleanProperty draggingVaultOver = new SimpleBooleanProperty(); private final BooleanProperty draggingVaultOver = new SimpleBooleanProperty();
private final ResourceBundle resourceBundle; private final ResourceBundle resourceBundle;
@@ -97,7 +94,7 @@ public class VaultListController implements FxController {
FxApplicationWindows appWindows, // FxApplicationWindows appWindows, //
Settings settings, // Settings settings, //
Dialogs dialogs, // Dialogs dialogs, //
EventMap eventMap) { FxFSEventList fxFSEventList) {
this.mainWindow = mainWindow; this.mainWindow = mainWindow;
this.vaults = vaults; this.vaults = vaults;
this.selectedVault = selectedVault; this.selectedVault = selectedVault;
@@ -110,13 +107,7 @@ public class VaultListController implements FxController {
this.dialogs = dialogs; this.dialogs = dialogs;
this.emptyVaultList = Bindings.isEmpty(vaults); this.emptyVaultList = Bindings.isEmpty(vaults);
this.eventMap = eventMap; this.unreadEvents = fxFSEventList.unreadEventsProperty();
this.newEventsPresent = new SimpleBooleanProperty(false);
eventMap.addListener((MapChangeListener<? super EventMap.EventKey, ? super VaultEvent>) change -> {
if (change.wasAdded()) {
newEventsPresent.setValue(true);
}
});
selectedVault.addListener(this::selectedVaultDidChange); selectedVault.addListener(this::selectedVaultDidChange);
cellSize = settings.compactMode.map(compact -> compact ? 30.0 : 60.0); cellSize = settings.compactMode.map(compact -> compact ? 30.0 : 60.0);
@@ -279,7 +270,6 @@ public class VaultListController implements FxController {
@FXML @FXML
public void showEventViewer() { public void showEventViewer() {
appWindows.showEventViewer(); appWindows.showEventViewer();
newEventsPresent.setValue(false);
} }
// Getter and Setter // Getter and Setter
@@ -307,11 +297,11 @@ public class VaultListController implements FxController {
return cellSize.getValue(); return cellSize.getValue();
} }
public ObservableValue<Boolean> newEventsPresentProperty() { public ObservableValue<Boolean> unreadEventsPresentProperty() {
return newEventsPresent; return unreadEvents;
} }
public boolean getNewEventsPresent() { public boolean getUnreadEventsPresent() {
return newEventsPresent.getValue(); return unreadEvents.getValue();
} }
} }
@@ -85,7 +85,7 @@ public class GeneralPreferencesController implements FxController {
var keychainSettingsConverter = new ServiceToSettingsConverter<>(keychainAccessProviders); var keychainSettingsConverter = new ServiceToSettingsConverter<>(keychainAccessProviders);
keychainBackendChoiceBox.getItems().addAll(keychainAccessProviders); keychainBackendChoiceBox.getItems().addAll(keychainAccessProviders);
keychainBackendChoiceBox.setValue(keychainSettingsConverter.fromString(settings.keychainProvider.get())); keychainBackendChoiceBox.setValue(keychainSettingsConverter.fromString(settings.keychainProvider.get()));
keychainBackendChoiceBox.setConverter(new KeychainProviderDisplayNameConverter()); keychainBackendChoiceBox.setConverter(new NamedServiceConverter<>());
Bindings.bindBidirectional(settings.keychainProvider, keychainBackendChoiceBox.valueProperty(), keychainSettingsConverter); Bindings.bindBidirectional(settings.keychainProvider, keychainBackendChoiceBox.valueProperty(), keychainSettingsConverter);
useKeychainCheckbox.selectedProperty().bindBidirectional(settings.useKeychain); useKeychainCheckbox.selectedProperty().bindBidirectional(settings.useKeychain);
keychainBackendChoiceBox.disableProperty().bind(useKeychainCheckbox.selectedProperty().not()); keychainBackendChoiceBox.disableProperty().bind(useKeychainCheckbox.selectedProperty().not());
@@ -106,13 +106,13 @@ public class GeneralPreferencesController implements FxController {
var idsAndNames = settings.directories.stream().collect(Collectors.toMap(vs -> vs.id, vs -> vs.displayName.getValue())); var idsAndNames = settings.directories.stream().collect(Collectors.toMap(vs -> vs.id, vs -> vs.displayName.getValue()));
if (!idsAndNames.isEmpty()) { if (!idsAndNames.isEmpty()) {
if (LOG.isDebugEnabled()) { if (LOG.isDebugEnabled()) {
LOG.debug("Migrating keychain entries {} from {} to {}", idsAndNames.keySet(), oldProvider.displayName(), newProvider.displayName()); LOG.debug("Migrating keychain entries {} from {} to {}", idsAndNames.keySet(), oldProvider.getName(), newProvider.getName());
} }
keychainMigrations = keychainMigrations.thenRunAsync(() -> { keychainMigrations = keychainMigrations.thenRunAsync(() -> {
try { try {
KeychainManager.migrate(oldProvider, newProvider, idsAndNames); KeychainManager.migrate(oldProvider, newProvider, idsAndNames);
} catch (KeychainAccessException e) { } catch (KeychainAccessException e) {
LOG.warn("Failed to migrate all entries from {} to {}", oldProvider.displayName(), newProvider.displayName(), e); LOG.warn("Failed to migrate all entries from {} to {}", oldProvider.getName(), newProvider.getName(), e);
} }
}, backgroundExecutor); }, backgroundExecutor);
} }
@@ -151,25 +151,6 @@ public class GeneralPreferencesController implements FxController {
} }
/* Helper classes */ /* Helper classes */
private static class KeychainProviderDisplayNameConverter extends StringConverter<KeychainAccessProvider> {
@Override
public String toString(KeychainAccessProvider provider) {
if (provider == null) {
return null;
} else {
return provider.displayName();
}
}
@Override
public KeychainAccessProvider fromString(String string) {
throw new UnsupportedOperationException();
}
}
private static class NamedServiceConverter<T extends NamedServiceProvider> extends StringConverter<T> { private static class NamedServiceConverter<T extends NamedServiceProvider> extends StringConverter<T> {
@Override @Override
+171 -8
View File
@@ -130,8 +130,7 @@
} }
.cryptic-text { .cryptic-text {
-fx-background-color: MAIN_BG; -fx-fill: TEXT_FILL;
-fx-text-fill: TEXT_FILL;
-fx-font-family: 'Fira Code'; -fx-font-family: 'Fira Code';
-fx-font-size: 1.1em; -fx-font-size: 1.1em;
} }
@@ -313,6 +312,10 @@
-fx-font-size: 1.0em; -fx-font-size: 1.0em;
} }
.list-cell .header-misc {
-fx-font-size: 1.0em;
}
.list-cell .detail-label { .list-cell .detail-label {
-fx-text-fill: TEXT_FILL_MUTED; -fx-text-fill: TEXT_FILL_MUTED;
-fx-font-size: 0.8em; -fx-font-size: 0.8em;
@@ -652,11 +655,8 @@
* * * *
******************************************************************************/ ******************************************************************************/
.update-indicator { .icon-update-indicator {
-fx-background-color: white, RED_5; -fx-fill: RED_5;
-fx-background-insets: 1px, 2px;
-fx-background-radius: 6px, 5px;
-fx-effect: dropshadow(three-pass-box, rgba(0, 0, 0, 0.8), 2, 0, 0, 0);
} }
/******************************************************************************* /*******************************************************************************
@@ -1022,4 +1022,167 @@
-fx-background-color: CONTROL_BORDER_NORMAL, CONTROL_BG_NORMAL; -fx-background-color: CONTROL_BORDER_NORMAL, CONTROL_BG_NORMAL;
-fx-background-insets: 0, 1px; -fx-background-insets: 0, 1px;
-fx-background-radius: 4px; -fx-background-radius: 4px;
} }
/*******************************************************************************
* *
* Decrypt Name Window
* *
******************************************************************************/
.decrypt-name-window .button-bar {
-fx-min-height:42px;
-fx-max-height:42px;
-fx-background-color: MAIN_BG;
-fx-border-color: transparent transparent CONTROL_BORDER_NORMAL transparent;
-fx-border-width: 0 0 1px 0;
}
.decrypt-name-window .button-bar .button-right {
-fx-border-color: transparent transparent transparent CONTROL_BORDER_NORMAL;
-fx-border-width: 0 0 0 1px;
-fx-background-color: MAIN_BG;
-fx-background-radius: 0px;
-fx-min-height: 42px;
-fx-max-height: 42px;
}
.decrypt-name-window .button-bar .button-right:armed {
-fx-background-color: CONTROL_BORDER_NORMAL, CONTROL_BG_ARMED;
}
.decrypt-name-window .table-view {
-fx-background-color: CONTROL_BORDER_NORMAL, CONTROL_BG_NORMAL;
-fx-background-insets: 0,1;
/* There is some oddness if padding is in em values rather than pixels,
in particular, the left border of the control doesn't show. */
-fx-padding: 1; /* 0.083333em; */
}
.table-view > .placeholder {
-fx-background-color: transparent;
-fx-background-radius: 0px;
}
.table-view > .placeholder > .button {
-fx-border-width: 0;
-fx-border-color: transparent;
-fx-background-radius: 0px;
}
.table-view:focused {
-fx-background-color: CONTROL_BORDER_FOCUSED, CONTROL_BG_NORMAL;
-fx-background-insets: 0, 1;
-fx-background-radius: 0, 0;
/* There is some oddness if padding is in em values rather than pixels,
in particular, the left border of the control doesn't show. */
-fx-padding: 1; /* 0.083333em; */
}
.table-view > .virtual-flow > .scroll-bar:vertical {
-fx-background-insets: 0, 0 0 0 1;
-fx-padding: -1 -1 -1 0;
}
.table-view > .virtual-flow > .corner {
-fx-background-color: CONTROL_BORDER_NORMAL, CONTROL_BG_NORMAL ;
-fx-background-insets: 0, 1 0 0 1;
}
/* Each row in the table is a table-row-cell. Inside a table-row-cell is any
number of table-cell. */
.table-row-cell {
-fx-background-color: GRAY_3, CONTROL_BG_NORMAL;
-fx-background-insets: 0, 0 0 1 0;
-fx-padding: 0.0em; /* 0 */
-fx-text-fill: TEXT_FILL;
}
.table-row-cell:odd {
-fx-background-color: GRAY_3, GRAY_1;
-fx-background-insets: 0, 0 0 1 0;
}
.table-cell {
-fx-padding: 3px 6px 3px 6px;
-fx-background-color: transparent;
-fx-border-color: transparent CONTROL_BORDER_NORMAL transparent transparent;
-fx-border-width: 1px;
-fx-cell-size: 30px;
-fx-text-fill: TEXT_FILL;
-fx-text-overrun: center-ellipsis;
}
.table-view:focused > .virtual-flow > .clipped-container > .sheet > .table-row-cell:filled:selected > .table-cell {
-fx-text-fill: TEXT_FILL;
}
/* selected, hover - not specified */
/* selected, focused, hover */
/* selected, focused */
/* selected */
.table-view:focused:cell-selection > .virtual-flow > .clipped-container > .sheet > .table-row-cell:filled > .table-cell:selected,
.table-view:focused:cell-selection > .virtual-flow > .clipped-container > .sheet > .table-row-cell:filled > .table-cell:focused:selected,
.table-view:focused:cell-selection > .virtual-flow > .clipped-container > .sheet > .table-row-cell:filled > .table-cell:focused:selected:hover {
-fx-background-color: CONTROL_PRIMARY_BG_NORMAL, PRIMARY_D1;
-fx-background-insets: 0 0 0 0, 1 1 1 3;
-fx-text-fill: TEXT_FILL;
}
/* focused */
.table-view:focused:cell-selection > .virtual-flow > .clipped-container > .sheet > .table-row-cell:filled > .table-cell:focused {
-fx-background-color: CONTROL_PRIMARY_BORDER_FOCUSED, CONTROL_PRIMARY_BG_NORMAL , CONTROL_BG_NORMAL;
-fx-background-insets: 0 1 0 0, 1 2 1 1, 2 3 2 2;
-fx-text-fill: TEXT_FILL;
}
/* focused, hover */
.table-view:focused:cell-selection > .virtual-flow > .clipped-container > .sheet > .table-row-cell:filled > .table-cell:focused:hover {
-fx-background-color: CONTROL_PRIMARY_BORDER_FOCUSED, CONTROL_PRIMARY_BG_NORMAL , PRIMARY_D2;
-fx-background-insets: 0 1 0 0, 1 2 1 1, 2 3 2 2;
-fx-text-fill: TEXT_FILL;
}
/* hover */
.table-view:cell-selection > .virtual-flow > .clipped-container > .sheet > .table-row-cell:filled > .table-cell:hover {
-fx-background-color: PRIMARY_D2;
-fx-text-fill: TEXT_FILL;
-fx-background-insets: 0 0 1 0;
}
/* The column-resize-line is shown when the user is attempting to resize a column. */
.table-view .column-resize-line {
-fx-background-color: CONTROL_BG_ARMED;
-fx-padding: 0.0em 0.0416667em 0.0em 0.0416667em; /* 0 0.571429 0 0.571429 */
}
/* This is the area behind the column headers. An ideal place to specify background
and border colors for the whole area (not individual column-header's). */
.table-view .column-header-background {
-fx-background-color: GRAY_2;
-fx-padding: 0;
}
/* The column header row is made up of a number of column-header, one for each
TableColumn, and a 'filler' area that extends from the right-most column
to the edge of the tableview, or up to the 'column control' button. */
.table-view .column-header {
-fx-text-fill: TEXT_FILL;
-fx-font-size: 1.083333em; /* 13pt ; 1 more than the default font */
-fx-size: 24;
-fx-border-style: solid;
-fx-border-color:
transparent
GRAY_3
GRAY_3
transparent;
-fx-border-insets: 0 0 0 0;
-fx-border-width: 0.083333em;
}
.table-view .column-header .label {
-fx-alignment: center;
}
.table-view .empty-table {
-fx-background-color: MAIN_BG;
-fx-font-size: 1.166667em; /* 14pt - 2 more than the default font */
}
+168 -8
View File
@@ -83,6 +83,7 @@
PROGRESS_INDICATOR_END: GRAY_4; PROGRESS_INDICATOR_END: GRAY_4;
PROGRESS_BAR_BG: GRAY_8; PROGRESS_BAR_BG: GRAY_8;
-fx-background-color: MAIN_BG; -fx-background-color: MAIN_BG;
-fx-text-fill: TEXT_FILL; -fx-text-fill: TEXT_FILL;
-fx-font-family: 'Open Sans'; -fx-font-family: 'Open Sans';
@@ -129,8 +130,7 @@
} }
.cryptic-text { .cryptic-text {
-fx-background-color: MAIN_BG; -fx-fill: TEXT_FILL;
-fx-text-fill: TEXT_FILL;
-fx-font-family: 'Fira Code'; -fx-font-family: 'Fira Code';
-fx-font-size: 1.1em; -fx-font-size: 1.1em;
} }
@@ -655,11 +655,8 @@
* * * *
******************************************************************************/ ******************************************************************************/
.update-indicator { .icon-update-indicator {
-fx-background-color: white, RED_5; -fx-fill: RED_5;
-fx-background-insets: 1px, 2px;
-fx-background-radius: 6px, 5px;
-fx-effect: dropshadow(three-pass-box, rgba(0, 0, 0, 0.8), 2, 0, 0, 0);
} }
/******************************************************************************* /*******************************************************************************
@@ -1025,4 +1022,167 @@
-fx-background-color: CONTROL_BORDER_NORMAL, CONTROL_BG_NORMAL; -fx-background-color: CONTROL_BORDER_NORMAL, CONTROL_BG_NORMAL;
-fx-background-insets: 0, 1px; -fx-background-insets: 0, 1px;
-fx-background-radius: 4px; -fx-background-radius: 4px;
} }
/*******************************************************************************
* *
* Decrypt Name Window
* *
******************************************************************************/
.decrypt-name-window .button-bar {
-fx-min-height:42px;
-fx-max-height:42px;
-fx-background-color: MAIN_BG;
-fx-border-color: transparent transparent CONTROL_BORDER_NORMAL transparent;
-fx-border-width: 0 0 1px 0;
}
.decrypt-name-window .button-bar .button-right {
-fx-border-color: transparent transparent transparent CONTROL_BORDER_NORMAL;
-fx-border-width: 0 0 0 1px;
-fx-background-color: MAIN_BG;
-fx-background-radius: 0px;
-fx-min-height: 42px;
-fx-max-height: 42px;
}
.decrypt-name-window .button-bar .button-right:armed {
-fx-background-color: CONTROL_BORDER_NORMAL, CONTROL_BG_ARMED;
}
.decrypt-name-window .table-view {
-fx-background-color: CONTROL_BORDER_NORMAL, CONTROL_BG_NORMAL;
-fx-background-insets: 0,1;
/* There is some oddness if padding is in em values rather than pixels,
in particular, the left border of the control doesn't show. */
-fx-padding: 1; /* 0.083333em; */
}
.table-view > .placeholder {
-fx-background-color: transparent;
-fx-background-radius: 0px;
}
.table-view > .placeholder > .button {
-fx-border-width: 0;
-fx-border-color: transparent;
-fx-background-radius: 0px;
}
.table-view:focused {
-fx-background-color: CONTROL_BORDER_FOCUSED, CONTROL_BG_NORMAL;
-fx-background-insets: 0, 1;
-fx-background-radius: 0, 0;
/* There is some oddness if padding is in em values rather than pixels,
in particular, the left border of the control doesn't show. */
-fx-padding: 1; /* 0.083333em; */
}
.table-view > .virtual-flow > .scroll-bar:vertical {
-fx-background-insets: 0, 0 0 0 1;
-fx-padding: -1 -1 -1 0;
}
.table-view > .virtual-flow > .corner {
-fx-background-color: CONTROL_BORDER_NORMAL, CONTROL_BG_NORMAL ;
-fx-background-insets: 0, 1 0 0 1;
}
/* Each row in the table is a table-row-cell. Inside a table-row-cell is any
number of table-cell. */
.table-row-cell {
-fx-background-color: GRAY_6, CONTROL_BG_NORMAL;
-fx-background-insets: 0, 0 0 1 0;
-fx-padding: 0.0em; /* 0 */
-fx-text-fill: TEXT_FILL;
}
.table-row-cell:odd {
-fx-background-color: GRAY_6, GRAY_9;
-fx-background-insets: 0, 0 0 1 0;
}
.table-cell {
-fx-padding: 3px 6px 3px 6px;
-fx-background-color: transparent;
-fx-border-color: transparent CONTROL_BORDER_NORMAL transparent transparent;
-fx-border-width: 1px;
-fx-cell-size: 30px;
-fx-text-fill: TEXT_FILL;
-fx-text-overrun: center-ellipsis;
}
.table-view:focused > .virtual-flow > .clipped-container > .sheet > .table-row-cell:filled:selected > .table-cell {
-fx-text-fill: TEXT_FILL;
}
/* selected, hover - not specified */
/* selected, focused, hover */
/* selected, focused */
/* selected */
.table-view:focused:cell-selection > .virtual-flow > .clipped-container > .sheet > .table-row-cell:filled > .table-cell:selected,
.table-view:focused:cell-selection > .virtual-flow > .clipped-container > .sheet > .table-row-cell:filled > .table-cell:focused:selected,
.table-view:focused:cell-selection > .virtual-flow > .clipped-container > .sheet > .table-row-cell:filled > .table-cell:focused:selected:hover {
-fx-background-color: CONTROL_PRIMARY_BG_NORMAL, CONTROL_BG_SELECTED;
-fx-background-insets: 0 0 0 0, 1 1 1 3;
-fx-text-fill: TEXT_FILL;
}
/* focused */
.table-view:focused:cell-selection > .virtual-flow > .clipped-container > .sheet > .table-row-cell:filled > .table-cell:focused {
-fx-background-color: CONTROL_PRIMARY_BORDER_FOCUSED, CONTROL_PRIMARY_BG_NORMAL , CONTROL_BG_NORMAL;
-fx-background-insets: 0 1 0 0, 1 2 1 1, 2 3 2 2;
-fx-text-fill: TEXT_FILL;
}
/* focused, hover */
.table-view:focused:cell-selection > .virtual-flow > .clipped-container > .sheet > .table-row-cell:filled > .table-cell:focused:hover {
-fx-background-color: CONTROL_PRIMARY_BORDER_FOCUSED, CONTROL_PRIMARY_BG_NORMAL , PRIMARY_L2;
-fx-background-insets: 0 1 0 0, 1 2 1 1, 2 3 2 2;
-fx-text-fill: TEXT_FILL;
}
/* hover */
.table-view:cell-selection > .virtual-flow > .clipped-container > .sheet > .table-row-cell:filled > .table-cell:hover {
-fx-background-color: PRIMARY_L2;
-fx-text-fill: TEXT_FILL;
-fx-background-insets: 0 0 1 0;
}
/* The column-resize-line is shown when the user is attempting to resize a column. */
.table-view .column-resize-line {
-fx-background-color: CONTROL_BG_ARMED;
-fx-padding: 0.0em 0.0416667em 0.0em 0.0416667em; /* 0 0.571429 0 0.571429 */
}
/* This is the area behind the column headers. An ideal place to specify background
and border colors for the whole area (not individual column-header's). */
.table-view .column-header-background {
-fx-background-color: GRAY_7;
-fx-padding: 0;
}
/* The column header row is made up of a number of column-header, one for each
TableColumn, and a 'filler' area that extends from the right-most column
to the edge of the tableview, or up to the 'column control' button. */
.table-view .column-header {
-fx-text-fill: TEXT_FILL;
-fx-font-size: 1.083333em; /* 13pt ; 1 more than the default font */
-fx-size: 24;
-fx-border-style: solid;
-fx-border-color:
CONTROL_BORDER_NORMAL
GRAY_5
GRAY_5
transparent;
-fx-border-insets: 0 0 0 0;
-fx-border-width: 0.083333em;
}
.table-view .column-header .label {
-fx-alignment: center;
}
.table-view .empty-table {
-fx-background-color: MAIN_BG;
-fx-font-size: 1.166667em; /* 14pt - 2 more than the default font */
}
+70
View File
@@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import org.cryptomator.ui.controls.FontAwesome5IconView?>
<?import org.cryptomator.ui.controls.FormattedLabel?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.control.Tooltip?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.Region?>
<?import javafx.scene.layout.VBox?>
<VBox xmlns="http://javafx.com/javafx"
xmlns:fx="http://javafx.com/fxml"
fx:controller="org.cryptomator.ui.decryptname.DecryptFileNamesViewController"
styleClass="decrypt-name-window"
minWidth="400"
maxWidth="400"
minHeight="145">
<HBox styleClass="button-bar" alignment="CENTER">
<padding>
<Insets left="6"/>
</padding>
<Region HBox.hgrow="ALWAYS"/>
<Button styleClass="button-right" contentDisplay="GRAPHIC_ONLY" onAction="#copyTableToClipboard">
<graphic>
<FontAwesome5IconView glyph="CLIPBOARD" glyphSize="16"/>
</graphic>
<tooltip>
<Tooltip text="%decryptNames.copyTable.tooltip"/>
</tooltip>
</Button>
<Button styleClass="button-right" contentDisplay="GRAPHIC_ONLY" onAction="#clearTable">
<graphic>
<FontAwesome5IconView glyph="TRASH" glyphSize="16"/>
</graphic>
<tooltip>
<Tooltip text="%decryptNames.clearTable.tooltip"/>
</tooltip>
</Button>
</HBox>
<TableView fx:id="cipherToCleartextTable" VBox.vgrow="ALWAYS">
<placeholder>
<Button alignment="CENTER" onAction="#selectFiles" text="${controller.dropZoneText}" contentDisplay="TOP" maxWidth="Infinity" maxHeight="Infinity">
<graphic>
<FontAwesome5IconView glyph="${controller.dropZoneIcon}" glyphSize="16"/>
</graphic>
</Button>
</placeholder>
<columns>
<TableColumn fx:id="ciphertextColumn" prefWidth="${cipherToCleartextTable.width * 0.5}">
<graphic>
<FontAwesome5IconView glyph="LOCK"/>
</graphic>
</TableColumn>
<TableColumn fx:id="cleartextColumn" prefWidth="${cipherToCleartextTable.width * 0.5}">
<graphic>
<FontAwesome5IconView glyph="LOCK_OPEN"/>
</graphic>
</TableColumn>
</columns>
</TableView>
<HBox>
<padding>
<Insets topRightBottomLeft="6"/>
</padding>
<Region HBox.hgrow="ALWAYS"/>
<FormattedLabel styleClass="label-small" format="%decryptNames.copyHint" arg1="${controller.copyToClipboardShortcutString}"/>
</HBox>
</VBox>
+1 -1
View File
@@ -20,7 +20,7 @@
<padding> <padding>
<Insets left="6" /> <Insets left="6" />
</padding> </padding>
<ChoiceBox fx:id="vaultFilterChoiceBox"/> <ChoiceBox fx:id="vaultFilterChoiceBox" minWidth="42"/>
<Region HBox.hgrow="ALWAYS"/> <Region HBox.hgrow="ALWAYS"/>
<Button styleClass="button-right" onAction="#clearEvents" contentDisplay="GRAPHIC_ONLY"> <Button styleClass="button-right" onAction="#clearEvents" contentDisplay="GRAPHIC_ONLY">
<graphic> <graphic>
@@ -58,6 +58,7 @@
<Tooltip text="%main.vaultDetail.locateEncryptedFileBtn.tooltip"/> <Tooltip text="%main.vaultDetail.locateEncryptedFileBtn.tooltip"/>
</tooltip> </tooltip>
</Button> </Button>
<!-- TODO: instead of showing a button, show on error a small dialog and if copied, show a tooltip -->
<Button styleClass="drag-n-drop" text="%main.vaultDetail.encryptedPathsCopied" minWidth="120" maxWidth="180" prefHeight="72" wrapText="true" textAlignment="CENTER" onAction="#chooseDecryptedFileAndReveal" contentDisplay="TOP" visible="${controller.ciphertextPathsCopied}" managed="${controller.ciphertextPathsCopied}"> <Button styleClass="drag-n-drop" text="%main.vaultDetail.encryptedPathsCopied" minWidth="120" maxWidth="180" prefHeight="72" wrapText="true" textAlignment="CENTER" onAction="#chooseDecryptedFileAndReveal" contentDisplay="TOP" visible="${controller.ciphertextPathsCopied}" managed="${controller.ciphertextPathsCopied}">
<graphic> <graphic>
<FontAwesome5IconView glyph="CHECK" glyphSize="15"/> <FontAwesome5IconView glyph="CHECK" glyphSize="15"/>
@@ -65,25 +66,14 @@
</Button> </Button>
</StackPane> </StackPane>
<!-- decrypt file name --> <!-- decrypt file name -->
<StackPane> <Button fx:id="decryptNameDropZone" styleClass="drag-n-drop" text="%main.vaultDetail.decryptName.buttonLabel" minWidth="120" maxWidth="180" prefHeight="72" wrapText="true" textAlignment="CENTER" onAction="#showDecryptNameWindow" contentDisplay="TOP">
<padding> <graphic>
<Insets topRightBottomLeft="0"/> <Text styleClass="cryptic-text" text="101010 → abc"/>
</padding> </graphic>
<Button fx:id="decryptNameDropZone" styleClass="drag-n-drop" text="%main.vaultDetail.decryptName.buttonLabel" minWidth="120" maxWidth="180" prefHeight="72" wrapText="true" textAlignment="CENTER" onAction="#chooseEncryptedFileAndCopyNames" contentDisplay="TOP" visible="${!controller.cleartextNamesCopied}" managed="${!controller.cleartextNamesCopied}"> <tooltip>
<graphic> <Tooltip text="%main.vaultDetail.decryptName.tooltip"/>
<Text styleClass="cryptic-text" text="101010 → abc"/> </tooltip>
</graphic> </Button>
<tooltip>
<Tooltip text="%main.vaultDetail.decryptName.tooltip"/>
</tooltip>
</Button>
<Button styleClass="drag-n-drop" text="%main.vaultDetail.decryptName.copied" minWidth="120" maxWidth="180" prefHeight="72" wrapText="true" textAlignment="CENTER" onAction="#chooseEncryptedFileAndCopyNames" contentDisplay="TOP" visible="${controller.cleartextNamesCopied}" managed="${controller.cleartextNamesCopied}">
<graphic>
<FontAwesome5IconView glyph="CHECK" glyphSize="15"/>
</graphic>
</Button>
</StackPane>
<Region HBox.hgrow="ALWAYS"/> <Region HBox.hgrow="ALWAYS"/>
<Button text="%main.vaultDetail.stats" minWidth="120" onAction="#showVaultStatistics" contentDisplay="BOTTOM" prefHeight="72"> <Button text="%main.vaultDetail.stats" minWidth="120" onAction="#showVaultStatistics" contentDisplay="BOTTOM" prefHeight="72">
+7 -1
View File
@@ -12,6 +12,10 @@
<?import javafx.scene.layout.StackPane?> <?import javafx.scene.layout.StackPane?>
<?import javafx.scene.layout.VBox?> <?import javafx.scene.layout.VBox?>
<?import javafx.scene.shape.Arc?> <?import javafx.scene.shape.Arc?>
<?import javafx.scene.shape.Circle?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.shape.Rectangle?>
<?import javafx.scene.layout.AnchorPane?>
<StackPane xmlns:fx="http://javafx.com/fxml" <StackPane xmlns:fx="http://javafx.com/fxml"
xmlns="http://javafx.com/javafx" xmlns="http://javafx.com/javafx"
fx:id="root" fx:id="root"
@@ -51,7 +55,9 @@
<Tooltip text="%main.vaultlist.showEventsButton.tooltip"/> <Tooltip text="%main.vaultlist.showEventsButton.tooltip"/>
</tooltip> </tooltip>
</Button> </Button>
<Region styleClass="update-indicator" visible="${controller.newEventsPresent}" mouseTransparent="true" StackPane.alignment="TOP_RIGHT" prefWidth="12" prefHeight="12" maxWidth="-Infinity" maxHeight="-Infinity"/> <AnchorPane mouseTransparent="true" minWidth="12" maxWidth="12" minHeight="12" maxHeight="12" StackPane.alignment="CENTER">
<Circle radius="4" styleClass="icon-update-indicator" AnchorPane.topAnchor="-8" AnchorPane.rightAnchor="-6" visible="${controller.unreadEventsPresent}" />
</AnchorPane>
</StackPane> </StackPane>
<Button onMouseClicked="#showPreferences" styleClass="button-right" alignment="CENTER" minWidth="20" contentDisplay="GRAPHIC_ONLY"> <Button onMouseClicked="#showPreferences" styleClass="button-right" alignment="CENTER" minWidth="20" contentDisplay="GRAPHIC_ONLY">
<graphic> <graphic>
+15 -4
View File
@@ -427,9 +427,7 @@ main.vaultDetail.locateEncryptedFileBtn.tooltip=Choose a file from your vault to
main.vaultDetail.encryptedPathsCopied=Paths Copied to Clipboard! main.vaultDetail.encryptedPathsCopied=Paths Copied to Clipboard!
main.vaultDetail.locateEncrypted.filePickerTitle=Select File Inside Vault main.vaultDetail.locateEncrypted.filePickerTitle=Select File Inside Vault
main.vaultDetail.decryptName.buttonLabel=Decrypt File Name main.vaultDetail.decryptName.buttonLabel=Decrypt File Name
main.vaultDetail.decryptName.filePickerTitle=Select encrypted file
main.vaultDetail.decryptName.tooltip=Choose an encrypted vault file to decrypt its name main.vaultDetail.decryptName.tooltip=Choose an encrypted vault file to decrypt its name
main.vaultDetail.decryptName.copied=Names copied to clipboard!
### Missing ### Missing
main.vaultDetail.missing.info=Cryptomator could not find a vault at this path. main.vaultDetail.missing.info=Cryptomator could not find a vault at this path.
main.vaultDetail.missing.recheck=Recheck main.vaultDetail.missing.recheck=Recheck
@@ -585,12 +583,25 @@ shareVault.hub.instruction.1=1. Share access of the encrypted vault folder via c
shareVault.hub.instruction.2=2. Grant access to team member in Cryptomator Hub. shareVault.hub.instruction.2=2. Grant access to team member in Cryptomator Hub.
shareVault.hub.openHub=Open Cryptomator Hub shareVault.hub.openHub=Open Cryptomator Hub
# Decrypt File Names
decryptNames.title=Decrypt File Names
decryptNames.filePicker.title=Select encrypted file
decryptNames.filePicker.extensionDescription=Cryptomator encrypted file
decryptNames.copyTable.tooltip=Copy table
decryptNames.clearTable.tooltip=Clear table
decryptNames.copyHint=Copy cell content with %s
decryptNames.dropZone.message=Drop files or click to select
decryptNames.dropZone.error.vaultInternalFiles=Vault internal files with no decrypt-able name selected
decryptNames.dropZone.error.foreignFiles=Files do not belong to vault "%s"
decryptNames.dropZone.error.noDirIdBackup=Directory of selected files does not contain dirId.c9r file
decryptNames.dropZone.error.generic=Failed to decrypt file names
# Event View # Event View
eventView.title=Events eventView.title=Events
eventView.filter.allVaults=All eventView.filter.allVaults=All
eventView.clearListButton.tooltip=Dismiss all eventView.clearListButton.tooltip=Clear list
## event list entries ## event list entries
eventView.entry.vaultLocked.message=***********
eventView.entry.vaultLocked.description=Unlock "%s" for details eventView.entry.vaultLocked.description=Unlock "%s" for details
eventView.entry.conflictResolved.message=Resolved conflict eventView.entry.conflictResolved.message=Resolved conflict
eventView.entry.conflictResolved.showDecrypted=Show decrypted file eventView.entry.conflictResolved.showDecrypted=Show decrypted file
@@ -121,3 +121,10 @@
#Retry If Readonly #Retry If Readonly
# Share Vault # Share Vault
# Decrypt File Names
# Event View
## event list entries
+14 -3
View File
@@ -1,6 +1,7 @@
# Locale Specific CSS files such as CJK, RTL,... # Locale Specific CSS files such as CJK, RTL,...
# Generics # Generics
generic.action.dismiss=تجاهل
## Button ## Button
generic.button.apply=تطبيق generic.button.apply=تطبيق
generic.button.back=رجوع generic.button.back=رجوع
@@ -176,6 +177,7 @@ hub.registerFailed.description.generic=حدث خطأ في عملية تسجيل
hub.registerFailed.description.deviceAlreadyExists=هذا الجهاز مسجل لمستخدم مختلف بالفعل. حاول تغيير حساب المستخدم أو استخدام جهاز مختلف. hub.registerFailed.description.deviceAlreadyExists=هذا الجهاز مسجل لمستخدم مختلف بالفعل. حاول تغيير حساب المستخدم أو استخدام جهاز مختلف.
### Unauthorized ### Unauthorized
hub.unauthorized.message=تم رفض الوصول hub.unauthorized.message=تم رفض الوصول
hub.unauthorized.description=غير مسموح لك بفتح هذا المستودع. اتصل بمالك المستودع لطلب الوصول.
### Requires Account Initialization ### Requires Account Initialization
hub.requireAccountInit.message=مطلوب اتخاذ إجراء hub.requireAccountInit.message=مطلوب اتخاذ إجراء
hub.requireAccountInit.description.0=للمتابعة، يرجى إكمال الخطوات المطلوبة في hub.requireAccountInit.description.0=للمتابعة، يرجى إكمال الخطوات المطلوبة في
@@ -281,7 +283,7 @@ preferences.title=تفضيلات
## General ## General
preferences.general=عام preferences.general=عام
preferences.general.startHidden=إخفاء النافذة عند بدء تشغيل Cryptomator preferences.general.startHidden=إخفاء النافذة عند بدء تشغيل Cryptomator
preferences.general.autoCloseVaults=اقفل الخزانات المفتوحة تلقائياً عند الإقلاع عن التطبيق preferences.general.autoCloseVaults=اقفل المخازن دون السؤال عند الإقلاع عن التطبيق
preferences.general.debugLogging=تمكين سجلات التصحيح preferences.general.debugLogging=تمكين سجلات التصحيح
preferences.general.debugDirectory=عرض ملفات السجل preferences.general.debugDirectory=عرض ملفات السجل
preferences.general.autoStart=تشغيل Cryptomator عند بدء تشغيل النظام preferences.general.autoStart=تشغيل Cryptomator عند بدء تشغيل النظام
@@ -421,7 +423,6 @@ main.vaultDetail.stats=إحصائيات الخزنة
main.vaultDetail.locateEncryptedFileBtn=تحديد موقع الملف المشفر main.vaultDetail.locateEncryptedFileBtn=تحديد موقع الملف المشفر
main.vaultDetail.locateEncryptedFileBtn.tooltip=اختر ملف من خزانتك لتحديد مكان نظيره المشفر main.vaultDetail.locateEncryptedFileBtn.tooltip=اختر ملف من خزانتك لتحديد مكان نظيره المشفر
main.vaultDetail.encryptedPathsCopied=تم نسخ مسارات الملفات إلى الحافظة! main.vaultDetail.encryptedPathsCopied=تم نسخ مسارات الملفات إلى الحافظة!
main.vaultDetail.filePickerTitle=إختر الملف من الخزنة
### Missing ### Missing
main.vaultDetail.missing.info=لم يتمكن Cryptomator من العثور على خزنة في هذا المسار. main.vaultDetail.missing.info=لم يتمكن Cryptomator من العثور على خزنة في هذا المسار.
main.vaultDetail.missing.recheck=إعادة الفحص main.vaultDetail.missing.recheck=إعادة الفحص
@@ -552,6 +553,10 @@ dokanySupportEnd.description=نوع وحدة التخزين Dokany لم يعد
dokanySupportEnd.preferencesBtn=فتح التفضيلات dokanySupportEnd.preferencesBtn=فتح التفضيلات
#Retry If Readonly #Retry If Readonly
retryIfReadonly.title=الوصول إلى المخزن المقيّد
retryIfReadonly.message=لا يوجد وصول للكتابة إلى مجلد المخزن
retryIfReadonly.description=Cryptomator لا يمكنه الكتابة إلى دليل المخزن. يمكنك تغيير المخزن ليكون للقراءة فقط وحاول مرة أخرى. يمكن تعطيل هذا الخيار في خيارات المخزن.
retryIfReadonly.retry=غيّر وأعد المحاولة
# Share Vault # Share Vault
shareVault.title=مشاركة الخزانة shareVault.title=مشاركة الخزانة
@@ -571,4 +576,10 @@ shareVault.hub.message=كيفية مشاركة خزانة Hub
shareVault.hub.description=لمشاركة محتوى الخزانة مع عضو آخر في الفريق، عليك القيام بخطوتين: shareVault.hub.description=لمشاركة محتوى الخزانة مع عضو آخر في الفريق، عليك القيام بخطوتين:
shareVault.hub.instruction.1=1. شارك الوصول إلى مجلد الخزانة المشفر عبر التخزين السحابي. shareVault.hub.instruction.1=1. شارك الوصول إلى مجلد الخزانة المشفر عبر التخزين السحابي.
shareVault.hub.instruction.2=2. امنح الوصول لعضو الفريق في Cryptomator Hub. shareVault.hub.instruction.2=2. امنح الوصول لعضو الفريق في Cryptomator Hub.
shareVault.hub.openHub=زيارة Cryptomator Hub shareVault.hub.openHub=زيارة Cryptomator Hub
# Decrypt File Names
# Event View
## event list entries
@@ -1,6 +1,7 @@
# Locale Specific CSS files such as CJK, RTL,... # Locale Specific CSS files such as CJK, RTL,...
# Generics # Generics
generic.action.dismiss=Кире ҡаҡ
## Button ## Button
generic.button.apply=Ҡуллан generic.button.apply=Ҡуллан
generic.button.back=Артҡа generic.button.back=Артҡа
@@ -269,7 +270,6 @@ preferences.title=Көйләүҙәр
## General ## General
preferences.general=Дөйөм preferences.general=Дөйөм
preferences.general.startHidden=Cryptomator башланған саҡта тәҙрәне йәшерергә preferences.general.startHidden=Cryptomator башланған саҡта тәҙрәне йәшерергә
preferences.general.autoCloseVaults=Ҡушымтанан сыҡҡан ваҡытта һаҡлағыстарҙы автоматик рәүештә бикләргә
preferences.general.debugLogging=Төҙөкләндереү журналын асырға preferences.general.debugLogging=Төҙөкләндереү журналын асырға
preferences.general.debugDirectory=Журнал файлдарын күрһәт preferences.general.debugDirectory=Журнал файлдарын күрһәт
preferences.general.autoStart=Система стартында Cryptomator-ҙы эшләтеп ебәрергә preferences.general.autoStart=Система стартында Cryptomator-ҙы эшләтеп ебәрергә
@@ -389,7 +389,6 @@ main.vaultDetail.stats=Һаҡлағыс статистикаһы
main.vaultDetail.locateEncryptedFileBtn=Шифрланған файлды тап main.vaultDetail.locateEncryptedFileBtn=Шифрланған файлды тап
main.vaultDetail.locateEncryptedFileBtn.tooltip=Шифрланған аналогын табыр өсөн һаҡлағыстан файл һайлағыҙ main.vaultDetail.locateEncryptedFileBtn.tooltip=Шифрланған аналогын табыр өсөн һаҡлағыстан файл һайлағыҙ
main.vaultDetail.encryptedPathsCopied=Юлдарҙын Clipboard-ҡа күсермәһе алынды! main.vaultDetail.encryptedPathsCopied=Юлдарҙын Clipboard-ҡа күсермәһе алынды!
main.vaultDetail.filePickerTitle=Һаҡлағыс эсендә файл һайлау
### Missing ### Missing
main.vaultDetail.missing.info=Cryptomator был юлдан һаҡлағыс таба алманы. main.vaultDetail.missing.info=Cryptomator был юлдан һаҡлағыс таба алманы.
main.vaultDetail.missing.recheck=Яңынан тикшер main.vaultDetail.missing.recheck=Яңынан тикшер
@@ -518,3 +517,10 @@ dokanySupportEnd.preferencesBtn=Көйләүҙәрҙе ас
#Retry If Readonly #Retry If Readonly
# Share Vault # Share Vault
# Decrypt File Names
# Event View
## event list entries
@@ -1,6 +1,7 @@
# Locale Specific CSS files such as CJK, RTL,... # Locale Specific CSS files such as CJK, RTL,...
# Generics # Generics
generic.action.dismiss=Адхіліць
## Button ## Button
generic.button.apply=Ужыць generic.button.apply=Ужыць
generic.button.back=Назад generic.button.back=Назад
@@ -258,7 +259,6 @@ preferences.title=Налады
## General ## General
preferences.general=Агульныя preferences.general=Агульныя
preferences.general.startHidden=Хаваць акно пры запуску Cryptomator preferences.general.startHidden=Хаваць акно пры запуску Cryptomator
preferences.general.autoCloseVaults=Замыкаць адчыненыя скарбніцы аўтаматычна пры выхадзе з праграмы
preferences.general.debugLogging=Уключыць пратакаляванне адладкі preferences.general.debugLogging=Уключыць пратакаляванне адладкі
preferences.general.debugDirectory=Паказаць файлы пратаколу preferences.general.debugDirectory=Паказаць файлы пратаколу
preferences.general.autoStart=Запускаць Cryptomator падчас запуску сістэмы preferences.general.autoStart=Запускаць Cryptomator падчас запуску сістэмы
@@ -376,7 +376,6 @@ main.vaultDetail.stats=Статыстыка скарбніцы
main.vaultDetail.locateEncryptedFileBtn=Знайсці зашыфраваны файл main.vaultDetail.locateEncryptedFileBtn=Знайсці зашыфраваны файл
main.vaultDetail.locateEncryptedFileBtn.tooltip=Абяры файл у тваёй скрабніцы, каб знайсці ягоны зашыфраваны адпаведнік main.vaultDetail.locateEncryptedFileBtn.tooltip=Абяры файл у тваёй скрабніцы, каб знайсці ягоны зашыфраваны адпаведнік
main.vaultDetail.encryptedPathsCopied=Шлях скапіяваны ў буфер абмену! main.vaultDetail.encryptedPathsCopied=Шлях скапіяваны ў буфер абмену!
main.vaultDetail.filePickerTitle=Абраць файл унутры скарбніцы
### Missing ### Missing
main.vaultDetail.missing.info=Cryptomator ня змог знайсці скарбніцу па гэтай сцежцы. main.vaultDetail.missing.info=Cryptomator ня змог знайсці скарбніцу па гэтай сцежцы.
main.vaultDetail.missing.recheck=Пераправерыць main.vaultDetail.missing.recheck=Пераправерыць
@@ -498,3 +497,10 @@ dokanySupportEnd.preferencesBtn=Адчыніць налады
#Retry If Readonly #Retry If Readonly
# Share Vault # Share Vault
# Decrypt File Names
# Event View
## event list entries
@@ -1,6 +1,7 @@
# Locale Specific CSS files such as CJK, RTL,... # Locale Specific CSS files such as CJK, RTL,...
# Generics # Generics
generic.action.dismiss=Отхвърляне
## Button ## Button
generic.button.apply=Прилагане generic.button.apply=Прилагане
generic.button.back=Назад generic.button.back=Назад
@@ -269,11 +270,11 @@ preferences.title=Настройки
## General ## General
preferences.general=Общи preferences.general=Общи
preferences.general.startHidden=Скриване на прозореца при отваряне на Криптоматор preferences.general.startHidden=Скриване на прозореца при отваряне на Криптоматор
preferences.general.autoCloseVaults=Заключване на хранилищата при затваряне на приложението
preferences.general.debugLogging=Дневник за отстраняване на дефекти preferences.general.debugLogging=Дневник за отстраняване на дефекти
preferences.general.debugDirectory=Файлове на дневниците preferences.general.debugDirectory=Файлове на дневниците
preferences.general.autoStart=Отваряне на Криптоматор при старт на системата preferences.general.autoStart=Отваряне на Криптоматор при старт на системата
preferences.general.keychainBackend=Съхраняванеа паролите в preferences.general.keychainBackend=Съхраняванеа паролите в
preferences.general.quickAccessService=Добавяне на отключените хранилища в зоната за бърз достъп
## Interface ## Interface
preferences.interface=Външен вид preferences.interface=Външен вид
preferences.interface.theme=Тема preferences.interface.theme=Тема
@@ -389,7 +390,6 @@ main.vaultDetail.stats=Статистики на хранилището
main.vaultDetail.locateEncryptedFileBtn=Намиране на шифровани файлове main.vaultDetail.locateEncryptedFileBtn=Намиране на шифровани файлове
main.vaultDetail.locateEncryptedFileBtn.tooltip=Изберете файл от хранилището, за да бъде намерено шифрованото му копие main.vaultDetail.locateEncryptedFileBtn.tooltip=Изберете файл от хранилището, за да бъде намерено шифрованото му копие
main.vaultDetail.encryptedPathsCopied=Пътищата са копирани! main.vaultDetail.encryptedPathsCopied=Пътищата са копирани!
main.vaultDetail.filePickerTitle=Изберете файл от хранилището
### Missing ### Missing
main.vaultDetail.missing.info=Криптоматор не намира хранилище на това място. main.vaultDetail.missing.info=Криптоматор не намира хранилище на това място.
main.vaultDetail.missing.recheck=Повторен опит main.vaultDetail.missing.recheck=Повторен опит
@@ -518,3 +518,10 @@ dokanySupportEnd.preferencesBtn=Към настройките
#Retry If Readonly #Retry If Readonly
# Share Vault # Share Vault
# Decrypt File Names
# Event View
## event list entries
@@ -185,3 +185,10 @@ vaultOptions.mount.mountPoint.directoryPickerButton=নির্বাচন ক
#Retry If Readonly #Retry If Readonly
# Share Vault # Share Vault
# Decrypt File Names
# Event View
## event list entries
@@ -321,3 +321,10 @@ quit.lockAndQuitBtn=Zaključaj i zatvori
#Retry If Readonly #Retry If Readonly
# Share Vault # Share Vault
# Decrypt File Names
# Event View
## event list entries
+14 -3
View File
@@ -1,6 +1,7 @@
# Locale Specific CSS files such as CJK, RTL,... # Locale Specific CSS files such as CJK, RTL,...
# Generics # Generics
generic.action.dismiss=Descartar
## Button ## Button
generic.button.apply=Aplica generic.button.apply=Aplica
generic.button.back=Enrere generic.button.back=Enrere
@@ -176,6 +177,7 @@ hub.registerFailed.description.generic=S'ha produït un error en el procés de r
hub.registerFailed.description.deviceAlreadyExists=El dispositiu ja ha estat registrat per un altre usuari. Mireu de canviar el compte d'usuari o feu servir un dispositiu diferent. hub.registerFailed.description.deviceAlreadyExists=El dispositiu ja ha estat registrat per un altre usuari. Mireu de canviar el compte d'usuari o feu servir un dispositiu diferent.
### Unauthorized ### Unauthorized
hub.unauthorized.message=Accés denegat hub.unauthorized.message=Accés denegat
hub.unauthorized.description=No estàs autoritzat a obrir aquesta caixa forta. Contacta amb el seu propietari per obtenir accés.
### Requires Account Initialization ### Requires Account Initialization
hub.requireAccountInit.message=Acció necessària hub.requireAccountInit.message=Acció necessària
hub.requireAccountInit.description.0=Per a continuar, si us plau, seguiu els passos necessaris en el vostre hub.requireAccountInit.description.0=Per a continuar, si us plau, seguiu els passos necessaris en el vostre
@@ -281,7 +283,7 @@ preferences.title=Preferències
## General ## General
preferences.general=General preferences.general=General
preferences.general.startHidden=Amaga la finestra quan s'inicia Cryptomator preferences.general.startHidden=Amaga la finestra quan s'inicia Cryptomator
preferences.general.autoCloseVaults=Bloquejar les caixes fortes automàticament quan surti de l'aplicació preferences.general.autoCloseVaults=Bloca les caixes fortes sense preguntar-ho en sortir de l'aplicació
preferences.general.debugLogging=Habilita el registre de depuració preferences.general.debugLogging=Habilita el registre de depuració
preferences.general.debugDirectory=Mostra els fitxers de registres preferences.general.debugDirectory=Mostra els fitxers de registres
preferences.general.autoStart=Executa Cryptomator en engegar el sistema preferences.general.autoStart=Executa Cryptomator en engegar el sistema
@@ -340,6 +342,7 @@ preferences.contribute.sponsor=Patrocinador
### Remove License Key Dialog ### Remove License Key Dialog
removeCert.title=Suprimeix certificat removeCert.title=Suprimeix certificat
removeCert.message=Eliminar certificat de col·laborador?
removeCert.description=Les característiques principals de Cryptomator no es veuen afectades per això. Ni l'accés a les vostres caixes fortes s'ha restringit ni el nivell de seguretat ha estat rebaixat. removeCert.description=Les característiques principals de Cryptomator no es veuen afectades per això. Ni l'accés a les vostres caixes fortes s'ha restringit ni el nivell de seguretat ha estat rebaixat.
#<-- Add entries for donations and code/translation/documentation contribution --> #<-- Add entries for donations and code/translation/documentation contribution -->
@@ -420,7 +423,6 @@ main.vaultDetail.stats=Estadístiques de la caixa forta
main.vaultDetail.locateEncryptedFileBtn=Trobar fitxer xifrat main.vaultDetail.locateEncryptedFileBtn=Trobar fitxer xifrat
main.vaultDetail.locateEncryptedFileBtn.tooltip=Esculli un fitxer de la caixa forta per trobar el seu homòleg xifrat main.vaultDetail.locateEncryptedFileBtn.tooltip=Esculli un fitxer de la caixa forta per trobar el seu homòleg xifrat
main.vaultDetail.encryptedPathsCopied=Rutes copiades al porta-retalls! main.vaultDetail.encryptedPathsCopied=Rutes copiades al porta-retalls!
main.vaultDetail.filePickerTitle=Seleccioni un fitxer dins la caixa forta
### Missing ### Missing
main.vaultDetail.missing.info=Cryptomator no ha trobat una caixa forta en aquesta ruta. main.vaultDetail.missing.info=Cryptomator no ha trobat una caixa forta en aquesta ruta.
main.vaultDetail.missing.recheck=Torna a comprovar main.vaultDetail.missing.recheck=Torna a comprovar
@@ -545,6 +547,9 @@ updateReminder.yesOnce=Sí, una vegada
updateReminder.yesAutomatically=Sí, automàticament updateReminder.yesAutomatically=Sí, automàticament
#Dokany Support End #Dokany Support End
dokanySupportEnd.title=Avís d'obsolescència
dokanySupportEnd.message=Fi de la compatibilitat amb Dokany
dokanySupportEnd.description=El tipus de volum Dokany ja no és compatible amb Cryptomator. La teva configuració canviarà al tipus de volum predeterminat. Pots veure el tipus de volum predeterminat en la configuració.
dokanySupportEnd.preferencesBtn=Obrir les Preferències dokanySupportEnd.preferencesBtn=Obrir les Preferències
#Retry If Readonly #Retry If Readonly
@@ -567,4 +572,10 @@ shareVault.hub.message=Com compartir una caixa forta al Hub
shareVault.hub.description=Per tal de compartir el contingut de la caixa forta amb un altre membre de l'equip, heu de seguir dos passos: shareVault.hub.description=Per tal de compartir el contingut de la caixa forta amb un altre membre de l'equip, heu de seguir dos passos:
shareVault.hub.instruction.1=1. Compartiu l'accés a la carpeta via emmagatzematge en el núvol. shareVault.hub.instruction.1=1. Compartiu l'accés a la carpeta via emmagatzematge en el núvol.
shareVault.hub.instruction.2=2. Doneu accés al membre de l'equip a Cryptomator Hub. shareVault.hub.instruction.2=2. Doneu accés al membre de l'equip a Cryptomator Hub.
shareVault.hub.openHub=Obre Cryptomator Hub shareVault.hub.openHub=Obre Cryptomator Hub
# Decrypt File Names
# Event View
## event list entries
@@ -1,6 +1,7 @@
# Locale Specific CSS files such as CJK, RTL,... # Locale Specific CSS files such as CJK, RTL,...
# Generics # Generics
generic.action.dismiss=Zrušit
## Button ## Button
generic.button.apply=Použít generic.button.apply=Použít
generic.button.back=Zpět generic.button.back=Zpět
@@ -272,7 +273,6 @@ preferences.title=Nastavení
## General ## General
preferences.general=Obecné preferences.general=Obecné
preferences.general.startHidden=Skrýt okno Cryptomatoru při spuštění preferences.general.startHidden=Skrýt okno Cryptomatoru při spuštění
preferences.general.autoCloseVaults=Zamknout trezory automaticky při ukončení aplikace
preferences.general.debugLogging=Ladicí režim preferences.general.debugLogging=Ladicí režim
preferences.general.debugDirectory=Ukázat soubory se záznamy událostí (log) preferences.general.debugDirectory=Ukázat soubory se záznamy událostí (log)
preferences.general.autoStart=Spustit Cryptomator při spuštění systému preferences.general.autoStart=Spustit Cryptomator při spuštění systému
@@ -390,7 +390,6 @@ main.vaultDetail.stats=Statistiky trezoru
main.vaultDetail.locateEncryptedFileBtn=Najít šifrovaný soubor main.vaultDetail.locateEncryptedFileBtn=Najít šifrovaný soubor
main.vaultDetail.locateEncryptedFileBtn.tooltip=Vyberte soubor z vašeho trezoru, abyste našli jeho šifrovaný protějšek main.vaultDetail.locateEncryptedFileBtn.tooltip=Vyberte soubor z vašeho trezoru, abyste našli jeho šifrovaný protějšek
main.vaultDetail.encryptedPathsCopied=Cesta souboru byla zkopírována do schránky! main.vaultDetail.encryptedPathsCopied=Cesta souboru byla zkopírována do schránky!
main.vaultDetail.filePickerTitle=Vyberte soubor uvnitř trezoru
### Missing ### Missing
main.vaultDetail.missing.info=Cryptomator nemohl najít trezor na této cestě. main.vaultDetail.missing.info=Cryptomator nemohl najít trezor na této cestě.
main.vaultDetail.missing.recheck=Znovu zkontrolovat main.vaultDetail.missing.recheck=Znovu zkontrolovat
@@ -534,4 +533,10 @@ shareVault.hub.message=Jak sdílet Hub trezor
shareVault.hub.description=Chcete-li sdílet obsah trezoru s jiným členem týmu, musíte provést dva kroky: shareVault.hub.description=Chcete-li sdílet obsah trezoru s jiným členem týmu, musíte provést dva kroky:
shareVault.hub.instruction.1=1. Sdílejte přístup ke šifrované složce trezoru prostřednictvím cloudového úložiště. shareVault.hub.instruction.1=1. Sdílejte přístup ke šifrované složce trezoru prostřednictvím cloudového úložiště.
shareVault.hub.instruction.2=2. Udělte přístup členovi týmu v Cryptomator Hubu. shareVault.hub.instruction.2=2. Udělte přístup členovi týmu v Cryptomator Hubu.
shareVault.hub.openHub=Otevřít Cryptomator Hub shareVault.hub.openHub=Otevřít Cryptomator Hub
# Decrypt File Names
# Event View
## event list entries
@@ -1,6 +1,7 @@
# Locale Specific CSS files such as CJK, RTL,... # Locale Specific CSS files such as CJK, RTL,...
# Generics # Generics
generic.action.dismiss=Luk
## Button ## Button
generic.button.apply=Anvend generic.button.apply=Anvend
generic.button.back=Tilbage generic.button.back=Tilbage
@@ -282,7 +283,6 @@ preferences.title=Præferencer
## General ## General
preferences.general=Generelt preferences.general=Generelt
preferences.general.startHidden=Skjul vinduet når Cryptomator starter preferences.general.startHidden=Skjul vinduet når Cryptomator starter
preferences.general.autoCloseVaults=Lås åbne bokse automatisk, når programmet afsluttes
preferences.general.debugLogging=Aktivér fejllogning preferences.general.debugLogging=Aktivér fejllogning
preferences.general.debugDirectory=Vis logfiler preferences.general.debugDirectory=Vis logfiler
preferences.general.autoStart=Start Cryptomator automatisk ved opstart preferences.general.autoStart=Start Cryptomator automatisk ved opstart
@@ -407,7 +407,6 @@ main.vaultDetail.stats=Boks statistik
main.vaultDetail.locateEncryptedFileBtn=Find Krypteret Fil main.vaultDetail.locateEncryptedFileBtn=Find Krypteret Fil
main.vaultDetail.locateEncryptedFileBtn.tooltip=Vælg en fil fra din boks for at finde dens krypterede modpart main.vaultDetail.locateEncryptedFileBtn.tooltip=Vælg en fil fra din boks for at finde dens krypterede modpart
main.vaultDetail.encryptedPathsCopied=Stier kopieret! main.vaultDetail.encryptedPathsCopied=Stier kopieret!
main.vaultDetail.filePickerTitle=Vælg fil inde i boks
### Missing ### Missing
main.vaultDetail.missing.info=Cryptomator kunne ikke finde en boks på denne sti. main.vaultDetail.missing.info=Cryptomator kunne ikke finde en boks på denne sti.
main.vaultDetail.missing.recheck=Kontrollér igen main.vaultDetail.missing.recheck=Kontrollér igen
@@ -554,4 +553,10 @@ shareVault.hub.message=Sådan deler du en Hub boks
shareVault.hub.description=For at dele indholdet i boksen med et andet holdmedlem skal du udføre to trin: shareVault.hub.description=For at dele indholdet i boksen med et andet holdmedlem skal du udføre to trin:
shareVault.hub.instruction.1=1. Del adgang til den krypterede boks-mappe vha. opbevaring i skyen. shareVault.hub.instruction.1=1. Del adgang til den krypterede boks-mappe vha. opbevaring i skyen.
shareVault.hub.instruction.2=2. Giv adgang til holdmedlem i Cryptomator Hub. shareVault.hub.instruction.2=2. Giv adgang til holdmedlem i Cryptomator Hub.
shareVault.hub.openHub=Åben Cryptomator Hub shareVault.hub.openHub=Åben Cryptomator Hub
# Decrypt File Names
# Event View
## event list entries
+50 -2
View File
@@ -1,6 +1,7 @@
# Locale Specific CSS files such as CJK, RTL,... # Locale Specific CSS files such as CJK, RTL,...
# Generics # Generics
generic.action.dismiss=Verwerfen
## Button ## Button
generic.button.apply=Übernehmen generic.button.apply=Übernehmen
generic.button.back=Zurück generic.button.back=Zurück
@@ -176,6 +177,7 @@ hub.registerFailed.description.generic=Im Registrierungsprozess ist ein Fehler a
hub.registerFailed.description.deviceAlreadyExists=Dieses Gerät ist bereits für einen anderen Benutzer registriert. Ändere das Benutzerkonto oder verwende ein anderes Gerät. hub.registerFailed.description.deviceAlreadyExists=Dieses Gerät ist bereits für einen anderen Benutzer registriert. Ändere das Benutzerkonto oder verwende ein anderes Gerät.
### Unauthorized ### Unauthorized
hub.unauthorized.message=Zugriff verweigert hub.unauthorized.message=Zugriff verweigert
hub.unauthorized.description=Du bist nicht berechtigt, diesen Tresor zu öffnen. Wende dich an den Tresoreigentümer, um Zugriff zu erhalten.
### Requires Account Initialization ### Requires Account Initialization
hub.requireAccountInit.message=Aktion erforderlich hub.requireAccountInit.message=Aktion erforderlich
hub.requireAccountInit.description.0=Um fortzufahren, führe bitte die erforderlichen Schritte in deinem hub.requireAccountInit.description.0=Um fortzufahren, führe bitte die erforderlichen Schritte in deinem
@@ -393,6 +395,7 @@ main.vaultlist.contextMenu.vaultoptions=Tresoroptionen anzeigen
main.vaultlist.contextMenu.reveal=Laufwerk anzeigen main.vaultlist.contextMenu.reveal=Laufwerk anzeigen
main.vaultlist.addVaultBtn.menuItemNew=Neuen Tresor erstellen... main.vaultlist.addVaultBtn.menuItemNew=Neuen Tresor erstellen...
main.vaultlist.addVaultBtn.menuItemExisting=Bestehenden Tresor öffnen... main.vaultlist.addVaultBtn.menuItemExisting=Bestehenden Tresor öffnen...
main.vaultlist.showEventsButton.tooltip=Ereignis-Ansicht öffnen
##Notificaition ##Notificaition
main.notification.updateAvailable=Eine neue Version ist verfügbar. main.notification.updateAvailable=Eine neue Version ist verfügbar.
main.notification.support=Unterstütze Cryptomator. main.notification.support=Unterstütze Cryptomator.
@@ -421,7 +424,9 @@ main.vaultDetail.stats=Tresorstatistik
main.vaultDetail.locateEncryptedFileBtn=Verschlüsselte Datei finden main.vaultDetail.locateEncryptedFileBtn=Verschlüsselte Datei finden
main.vaultDetail.locateEncryptedFileBtn.tooltip=Wähle eine Datei aus deinem Tresor aus, um das verschlüsselte Gegenstück zu finden main.vaultDetail.locateEncryptedFileBtn.tooltip=Wähle eine Datei aus deinem Tresor aus, um das verschlüsselte Gegenstück zu finden
main.vaultDetail.encryptedPathsCopied=Pfade in Zwischenablage kopiert! main.vaultDetail.encryptedPathsCopied=Pfade in Zwischenablage kopiert!
main.vaultDetail.filePickerTitle=Datei im Tresor auswählen main.vaultDetail.locateEncrypted.filePickerTitle=Datei im Tresor auswählen
main.vaultDetail.decryptName.buttonLabel=Dateiname entschlüsseln
main.vaultDetail.decryptName.tooltip=Wählen eine verschlüsselte Tresordatei, um ihren Namen zu entschlüsseln
### Missing ### Missing
main.vaultDetail.missing.info=Cryptomator konnte keinen Tresor mit diesem Pfad finden. main.vaultDetail.missing.info=Cryptomator konnte keinen Tresor mit diesem Pfad finden.
main.vaultDetail.missing.recheck=Erneut prüfen main.vaultDetail.missing.recheck=Erneut prüfen
@@ -552,6 +557,10 @@ dokanySupportEnd.description=Der Laufwerkstyp Dokany wird von Cryptomator nicht
dokanySupportEnd.preferencesBtn=Einstellungen öffnen dokanySupportEnd.preferencesBtn=Einstellungen öffnen
#Retry If Readonly #Retry If Readonly
retryIfReadonly.title=Eingeschränkter Tresorzugriff
retryIfReadonly.message=Kein Schreibzugriff auf Tresor
retryIfReadonly.description=Cryptomator kann nicht in das Verzeichnis des Tresors schreiben. Du kannst den Tresor auf schreibgeschützt umstellen und es erneut versuchen. Diese Option kann in den Tresoroptionen deaktiviert werden.
retryIfReadonly.retry=Ändern und wiederholen
# Share Vault # Share Vault
shareVault.title=Tresor teilen shareVault.title=Tresor teilen
@@ -571,4 +580,43 @@ shareVault.hub.message=Teilen eines Hub-Tresors
shareVault.hub.description=Zur Freigabe des Tresorinhalts für ein anderes Teammitglied sind zwei Schritte erforderlich: shareVault.hub.description=Zur Freigabe des Tresorinhalts für ein anderes Teammitglied sind zwei Schritte erforderlich:
shareVault.hub.instruction.1=1. Teile den Zugriff auf den verschlüsselten Tresorordner über den Cloud-Speicher. shareVault.hub.instruction.1=1. Teile den Zugriff auf den verschlüsselten Tresorordner über den Cloud-Speicher.
shareVault.hub.instruction.2=2. Füge das Teammitglied in Cryptomator Hub als Tresormitglied hinzu. shareVault.hub.instruction.2=2. Füge das Teammitglied in Cryptomator Hub als Tresormitglied hinzu.
shareVault.hub.openHub=Cryptomator Hub öffnen shareVault.hub.openHub=Cryptomator Hub öffnen
# Decrypt File Names
decryptNames.title=Dateinamen entschlüsseln
decryptNames.filePicker.title=Verschlüsselte Datei auswählen
decryptNames.filePicker.extensionDescription=Cryptomator-verschlüsselte Datei
decryptNames.copyTable.tooltip=Tabelle kopieren
decryptNames.clearTable.tooltip=Tabelle leeren
decryptNames.copyHint=Inhalt der Zelle mit %s kopieren
decryptNames.dropZone.message=Dateien ablegen oder zum Auswählen klicken
decryptNames.dropZone.error.vaultInternalFiles=Tresor interne Dateien mit nicht-entschlüsselbaren Namen ausgewählt
decryptNames.dropZone.error.foreignFiles=Dateien gehören nicht zum Tresor "%s"
decryptNames.dropZone.error.noDirIdBackup=Verzeichnis der ausgewählten Dateien enthält keine dirId.c9r Datei
decryptNames.dropZone.error.generic=Fehler beim Entschlüsseln der Dateinamen
# Event View
eventView.title=Ereignisse
eventView.filter.allVaults=Alle
eventView.clearListButton.tooltip=Liste leeren
## event list entries
eventView.entry.vaultLocked.description=Entsperre "%s" für Details
eventView.entry.conflictResolved.message=Konflikt gelöst
eventView.entry.conflictResolved.showDecrypted=Entschlüsselte Datei anzeigen
eventView.entry.conflictResolved.copyDecrypted=Pfad der entschlüsselten Datei kopieren
eventView.entry.conflict.message=Konfliktlösung fehlgeschlagen
eventView.entry.conflict.showDecrypted=Entschlüsselte, ursprüngliche Datei anzeigen
eventView.entry.conflict.copyDecrypted=Entschlüsselten, ursprünglicher Pfad kopieren
eventView.entry.conflict.showEncrypted=Zeige verschlüsselte Konfliktdatei
eventView.entry.conflict.copyEncrypted=Verschlüsselten Konfliktpfad kopieren
eventView.entry.decryptionFailed.message=Entschlüsselung fehlgeschlagen
eventView.entry.decryptionFailed.showEncrypted=Verschlüsselte Datei anzeigen
eventView.entry.decryptionFailed.copyEncrypted=Pfad der verschlüsselten Datei kopieren
eventView.entry.brokenDirFile.message=Ungültiger Verzeichnislink
eventView.entry.brokenDirFile.showEncrypted=Defekten, verschlüsselten Link anzeigen
eventView.entry.brokenDirFile.copyEncrypted=Pfad des ungültigen Links kopieren
eventView.entry.brokenFileNode.message=Fehlender Dateisystemknoten
eventView.entry.brokenFileNode.showEncrypted=Beschädigten, verschlüsselten Knoten anzeigen
eventView.entry.brokenFileNode.copyEncrypted=Pfad des kaputten, verschlüsselten Knotens kopieren
eventView.entry.brokenFileNode.copyDecrypted=Pfad der entschlüsselten Datei kopieren
+10 -3
View File
@@ -1,6 +1,7 @@
# Locale Specific CSS files such as CJK, RTL,... # Locale Specific CSS files such as CJK, RTL,...
# Generics # Generics
generic.action.dismiss=Παράβλεψη
## Button ## Button
generic.button.apply=Εφαρμογή generic.button.apply=Εφαρμογή
generic.button.back=Πίσω generic.button.back=Πίσω
@@ -282,7 +283,7 @@ preferences.title=Προτιμήσεις
## General ## General
preferences.general=Γενικά preferences.general=Γενικά
preferences.general.startHidden=Απόκρυψη παραθύρου όταν ξεκινά το Cryptomator preferences.general.startHidden=Απόκρυψη παραθύρου όταν ξεκινά το Cryptomator
preferences.general.autoCloseVaults=Αυτόματο κλείδωμα ανοιγμένης κρύπτης κατά την έξοδο της εφαρμογής preferences.general.autoCloseVaults=Κλείδωμα κρυπτών χωρίς ερώτηση κατά την έξοδο από την εφαρμογή
preferences.general.debugLogging=Ενεργοποίηση καταγραφής σφαλμάτων preferences.general.debugLogging=Ενεργοποίηση καταγραφής σφαλμάτων
preferences.general.debugDirectory=Αποκάλυψη αρχείων καταγραφής preferences.general.debugDirectory=Αποκάλυψη αρχείων καταγραφής
preferences.general.autoStart=Εκκίνηση Cryptomator στην εκκίνηση του συστήματος preferences.general.autoStart=Εκκίνηση Cryptomator στην εκκίνηση του συστήματος
@@ -422,7 +423,6 @@ main.vaultDetail.stats=Στατιστικά Vault
main.vaultDetail.locateEncryptedFileBtn=Εντοπισμός Κρυπτογραφημένου Αρχείου main.vaultDetail.locateEncryptedFileBtn=Εντοπισμός Κρυπτογραφημένου Αρχείου
main.vaultDetail.locateEncryptedFileBtn.tooltip=Επιλέξτε ένα αρχείο από την κρύπτη σας για να εντοπίσετε το κρυπτογραφημένο αντίστοιχο main.vaultDetail.locateEncryptedFileBtn.tooltip=Επιλέξτε ένα αρχείο από την κρύπτη σας για να εντοπίσετε το κρυπτογραφημένο αντίστοιχο
main.vaultDetail.encryptedPathsCopied=Οι Διαδρομές Αντιγράφηκαν στο Πρόχειρο! main.vaultDetail.encryptedPathsCopied=Οι Διαδρομές Αντιγράφηκαν στο Πρόχειρο!
main.vaultDetail.filePickerTitle=Επιλογή Αρχείου Μέσα Στην Κρύπτη
### Missing ### Missing
main.vaultDetail.missing.info=Cryptomator δεν βρήκε vault σε αυτόν τον κατάλογο. main.vaultDetail.missing.info=Cryptomator δεν βρήκε vault σε αυτόν τον κατάλογο.
main.vaultDetail.missing.recheck=Επανέλεγχος main.vaultDetail.missing.recheck=Επανέλεγχος
@@ -576,4 +576,11 @@ shareVault.hub.message=Πώς να μοιραστείτε μια κρύπτη Hu
shareVault.hub.description=Για να μοιραστείτε το περιεχόμενο της κρύπτης με άλλο μέλος της ομάδας, πρέπει να εκτελέσετε δύο βήματα: shareVault.hub.description=Για να μοιραστείτε το περιεχόμενο της κρύπτης με άλλο μέλος της ομάδας, πρέπει να εκτελέσετε δύο βήματα:
shareVault.hub.instruction.1=1. Μοιραστείτε την πρόσβαση στον κρυπτογραφημένο φάκελο κρύπτης μέσω του χώρου αποθήκευσης στο cloud. shareVault.hub.instruction.1=1. Μοιραστείτε την πρόσβαση στον κρυπτογραφημένο φάκελο κρύπτης μέσω του χώρου αποθήκευσης στο cloud.
shareVault.hub.instruction.2=2. Παραχωρήστε πρόσβαση σε μέλος της ομάδας στο Cryptomator Hub. shareVault.hub.instruction.2=2. Παραχωρήστε πρόσβαση σε μέλος της ομάδας στο Cryptomator Hub.
shareVault.hub.openHub=Ανοίξτε το Cryptomator Hub shareVault.hub.openHub=Ανοίξτε το Cryptomator Hub
# Decrypt File Names
# Event View
eventView.filter.allVaults=Όλες
## event list entries
+46 -3
View File
@@ -1,6 +1,7 @@
# Locale Specific CSS files such as CJK, RTL,... # Locale Specific CSS files such as CJK, RTL,...
# Generics # Generics
generic.action.dismiss=Descartar
## Button ## Button
generic.button.apply=Aplicar generic.button.apply=Aplicar
generic.button.back=Volver generic.button.back=Volver
@@ -282,7 +283,7 @@ preferences.title=Preferencias
## General ## General
preferences.general=General preferences.general=General
preferences.general.startHidden=Ocultar ventana al iniciar Cryptomator preferences.general.startHidden=Ocultar ventana al iniciar Cryptomator
preferences.general.autoCloseVaults=Bloquear automáticamente las bóvedas abiertas al salir de la aplicación preferences.general.autoCloseVaults=Bloquear bóvedas sin preguntar al salir de la aplicación
preferences.general.debugLogging=Habilitar registro de depuración preferences.general.debugLogging=Habilitar registro de depuración
preferences.general.debugDirectory=Revelar archivos de registro preferences.general.debugDirectory=Revelar archivos de registro
preferences.general.autoStart=Cargar Cryptomator al iniciar el sistema preferences.general.autoStart=Cargar Cryptomator al iniciar el sistema
@@ -394,6 +395,7 @@ main.vaultlist.contextMenu.vaultoptions=Mostrar opciones de la bóveda
main.vaultlist.contextMenu.reveal=Revelar unidad main.vaultlist.contextMenu.reveal=Revelar unidad
main.vaultlist.addVaultBtn.menuItemNew=Crear Bóveda Nueva... main.vaultlist.addVaultBtn.menuItemNew=Crear Bóveda Nueva...
main.vaultlist.addVaultBtn.menuItemExisting=Abrir Bóveda Existente... main.vaultlist.addVaultBtn.menuItemExisting=Abrir Bóveda Existente...
main.vaultlist.showEventsButton.tooltip=Abrir vista de evento
##Notificaition ##Notificaition
main.notification.updateAvailable=Existen actualizaciones disponibles. main.notification.updateAvailable=Existen actualizaciones disponibles.
main.notification.support=Soporte de Cryptomator. main.notification.support=Soporte de Cryptomator.
@@ -422,7 +424,9 @@ main.vaultDetail.stats=Estadísticas de la bóveda
main.vaultDetail.locateEncryptedFileBtn=Ubicar archivo cifrado main.vaultDetail.locateEncryptedFileBtn=Ubicar archivo cifrado
main.vaultDetail.locateEncryptedFileBtn.tooltip=Elija un archivo de su bóveda para ubicar su contraparte cifrada main.vaultDetail.locateEncryptedFileBtn.tooltip=Elija un archivo de su bóveda para ubicar su contraparte cifrada
main.vaultDetail.encryptedPathsCopied=¡Rutas copiadas al portapapeles! main.vaultDetail.encryptedPathsCopied=¡Rutas copiadas al portapapeles!
main.vaultDetail.filePickerTitle=Seleccionar archivo dentro de la bóveda main.vaultDetail.locateEncrypted.filePickerTitle=Seleccionar archivo dentro de la bóveda
main.vaultDetail.decryptName.buttonLabel=Descifrar nombre de archivo
main.vaultDetail.decryptName.tooltip=Elija un archivo de bóveda cifrado para descifrar su nombre
### Missing ### Missing
main.vaultDetail.missing.info=Cryptomator no pudo encontrar una bóveda en esta ruta. main.vaultDetail.missing.info=Cryptomator no pudo encontrar una bóveda en esta ruta.
main.vaultDetail.missing.recheck=Volver a comprobar main.vaultDetail.missing.recheck=Volver a comprobar
@@ -576,4 +580,43 @@ shareVault.hub.message=Cómo compartir una bóveda de Hub
shareVault.hub.description=Para compartir el contenido de la bóveda con otro miembro del equipo, tiene que realizar dos pasos: shareVault.hub.description=Para compartir el contenido de la bóveda con otro miembro del equipo, tiene que realizar dos pasos:
shareVault.hub.instruction.1=1. Comparta el acceso a la carpeta de la bóveda cifrada a través del almacenamiento en la nube. shareVault.hub.instruction.1=1. Comparta el acceso a la carpeta de la bóveda cifrada a través del almacenamiento en la nube.
shareVault.hub.instruction.2=2. Conceda el acceso al miembro del equipo en Cryptomator Hub. shareVault.hub.instruction.2=2. Conceda el acceso al miembro del equipo en Cryptomator Hub.
shareVault.hub.openHub=Abrir Cryptomator Hub shareVault.hub.openHub=Abrir Cryptomator Hub
# Decrypt File Names
decryptNames.title=Descifrar nombre de archivos
decryptNames.filePicker.title=Seleccione archivo cifrado
decryptNames.filePicker.extensionDescription=Archivo cifrado Cryptomator
decryptNames.copyTable.tooltip=Copiar tabla
decryptNames.clearTable.tooltip=Limpiar tabla
decryptNames.copyHint=Copiar contenido de celda con %s
decryptNames.dropZone.message=Soltar archivos o hacer clic para seleccionar
decryptNames.dropZone.error.vaultInternalFiles=Archivos internos de la bóveda sin nombre descifrable seleccionado
decryptNames.dropZone.error.foreignFiles=Los archivos no pertenecen a la bóveda "%s"
decryptNames.dropZone.error.noDirIdBackup=El directorio de los archivos seleccionados no contiene el archivo dirId.c9r
decryptNames.dropZone.error.generic=Error al descifrar nombre de archivos
# Event View
eventView.title=Eventos
eventView.filter.allVaults=Todos
eventView.clearListButton.tooltip=Borrar lista
## event list entries
eventView.entry.vaultLocked.description=Desbloquear "%s" para más detalles
eventView.entry.conflictResolved.message=Conflicto resuelto
eventView.entry.conflictResolved.showDecrypted=Mostrar archivo descifrado
eventView.entry.conflictResolved.copyDecrypted=Copiar ruta descifrada
eventView.entry.conflict.message=Resolución de conflictos fallida
eventView.entry.conflict.showDecrypted=Mostrar archivo descifrado, original
eventView.entry.conflict.copyDecrypted=Copiar ruta descifrada, original
eventView.entry.conflict.showEncrypted=Mostrar archivo en conflicto, cifrado
eventView.entry.conflict.copyEncrypted=Copiar ruta en conflicto, cifrada
eventView.entry.decryptionFailed.message=Desencriptación fallida
eventView.entry.decryptionFailed.showEncrypted=Mostrar archivo cifrado
eventView.entry.decryptionFailed.copyEncrypted=Copiar ruta cifrada
eventView.entry.brokenDirFile.message=Enlace de directorio roto
eventView.entry.brokenDirFile.showEncrypted=Mostrar enlace roto, cifrado
eventView.entry.brokenDirFile.copyEncrypted=Copiar ruta del enlace roto
eventView.entry.brokenFileNode.message=Nodo de sistema de archivos roto
eventView.entry.brokenFileNode.showEncrypted=Mostrar nodo roto, cifrado
eventView.entry.brokenFileNode.copyEncrypted=Copiar ruta del enlace roto, encriptado
eventView.entry.brokenFileNode.copyDecrypted=Copiar ruta descifrada
+16 -1
View File
@@ -1,8 +1,9 @@
# Locale Specific CSS files such as CJK, RTL,... # Locale Specific CSS files such as CJK, RTL,...
# Generics # Generics
generic.action.dismiss=لغو
## Button ## Button
generic.button.apply=درخواست generic.button.apply=اعمال
generic.button.back=بازگشت generic.button.back=بازگشت
generic.button.cancel=انصراف generic.button.cancel=انصراف
generic.button.change=تغییر generic.button.change=تغییر
@@ -106,11 +107,14 @@ addvaultwizard.existing.chooseBtn=انتخاب کنید…
unlock.unlockBtn=بازکردن قفل unlock.unlockBtn=بازکردن قفل
## Select ## Select
## Success ## Success
unlock.success.revealBtn=نمایش درایو
## Failure ## Failure
## Hub ## Hub
hub.noKeychain.openBtn=باز کردن تنظیمات
### Waiting ### Waiting
### Receive Key ### Receive Key
### Register Device ### Register Device
hub.register.message=دستگاه جدید
### Register Device Legacy ### Register Device Legacy
### Registration Success ### Registration Success
hub.registerSuccess.unlockBtn=بازکردن قفل hub.registerSuccess.unlockBtn=بازکردن قفل
@@ -170,11 +174,13 @@ preferences.updates.upToDate=Cryptomator به روز می باشد.
# Main Window # Main Window
## Vault List ## Vault List
main.vaultlist.contextMenu.lock=قفل main.vaultlist.contextMenu.lock=قفل
main.vaultlist.contextMenu.reveal=نمایش درایو
##Notificaition ##Notificaition
## Vault Detail ## Vault Detail
### Welcome ### Welcome
### Locked ### Locked
### Unlocked ### Unlocked
main.vaultDetail.revealBtn=نمایش درایو
main.vaultDetail.lockBtn=قفل main.vaultDetail.lockBtn=قفل
### Missing ### Missing
### Needs Migration ### Needs Migration
@@ -185,6 +191,7 @@ main.vaultDetail.lockBtn=قفل
# Vault Options # Vault Options
## General ## General
vaultOptions.general.vaultName=نام گاوصندوق vaultOptions.general.vaultName=نام گاوصندوق
vaultOptions.general.actionAfterUnlock.reveal=نمایش درایو
## Mount ## Mount
vaultOptions.mount.mountPoint.directoryPickerButton=انتخاب کنید… vaultOptions.mount.mountPoint.directoryPickerButton=انتخاب کنید…
@@ -209,7 +216,15 @@ vaultOptions.mount.mountPoint.directoryPickerButton=انتخاب کنید…
# Update Reminder # Update Reminder
#Dokany Support End #Dokany Support End
dokanySupportEnd.preferencesBtn=باز کردن تنظیمات
#Retry If Readonly #Retry If Readonly
# Share Vault # Share Vault
# Decrypt File Names
# Event View
## event list entries
@@ -1,6 +1,7 @@
# Locale Specific CSS files such as CJK, RTL,... # Locale Specific CSS files such as CJK, RTL,...
# Generics # Generics
generic.action.dismiss=Ohita
## Button ## Button
generic.button.apply=Käytä generic.button.apply=Käytä
generic.button.back=Takaisin generic.button.back=Takaisin
@@ -281,7 +282,6 @@ preferences.title=Asetukset
## General ## General
preferences.general=Yleiset preferences.general=Yleiset
preferences.general.startHidden=Piilota ikkuna kun Cryptomator käynnistyy preferences.general.startHidden=Piilota ikkuna kun Cryptomator käynnistyy
preferences.general.autoCloseVaults=Lukitse avoimet holvit automaattisesti kun ohjelma sammutetaan
preferences.general.debugLogging=Ota virheloki käyttöön preferences.general.debugLogging=Ota virheloki käyttöön
preferences.general.debugDirectory=Näytä lokitiedostot preferences.general.debugDirectory=Näytä lokitiedostot
preferences.general.autoStart=Käynnistä Cryptomator järjestelmän käynnistyessä preferences.general.autoStart=Käynnistä Cryptomator järjestelmän käynnistyessä
@@ -419,7 +419,6 @@ main.vaultDetail.stats=Holvin tilastot
main.vaultDetail.locateEncryptedFileBtn=Etsi salattu tiedosto main.vaultDetail.locateEncryptedFileBtn=Etsi salattu tiedosto
main.vaultDetail.locateEncryptedFileBtn.tooltip=Valitse tiedosto holvistasi löytääksesi sen salatun vastineen main.vaultDetail.locateEncryptedFileBtn.tooltip=Valitse tiedosto holvistasi löytääksesi sen salatun vastineen
main.vaultDetail.encryptedPathsCopied=Polut kopioitu leikepöydälle! main.vaultDetail.encryptedPathsCopied=Polut kopioitu leikepöydälle!
main.vaultDetail.filePickerTitle=Valitse tiedosto holvin sisältä
### Missing ### Missing
main.vaultDetail.missing.info=Cryptomator ei löytänyt täältä holvia. main.vaultDetail.missing.info=Cryptomator ei löytänyt täältä holvia.
main.vaultDetail.missing.recheck=Tarkista uudelleen main.vaultDetail.missing.recheck=Tarkista uudelleen
@@ -559,4 +558,10 @@ shareVault.visitHub=Käy Cryptomator Hubissa
shareVault.hub.message=Kuinka jakaa Hub -holvi shareVault.hub.message=Kuinka jakaa Hub -holvi
shareVault.hub.instruction.1=1. Jaa käyttöoikeus salattuun holvikansioon pilvipalvelun kautta. shareVault.hub.instruction.1=1. Jaa käyttöoikeus salattuun holvikansioon pilvipalvelun kautta.
shareVault.hub.openHub=Avaa Cryptomator Hub shareVault.hub.openHub=Avaa Cryptomator Hub
# Decrypt File Names
# Event View
## event list entries
@@ -1,6 +1,7 @@
# Locale Specific CSS files such as CJK, RTL,... # Locale Specific CSS files such as CJK, RTL,...
# Generics # Generics
generic.action.dismiss=I-dismiss
## Button ## Button
generic.button.apply=I-apply generic.button.apply=I-apply
generic.button.back=Bumalik generic.button.back=Bumalik
@@ -281,7 +282,6 @@ preferences.title=Mga Kagustuhan
## General ## General
preferences.general=Heneral preferences.general=Heneral
preferences.general.startHidden=Itago ang window kapag sinimulan ang Cryptomator preferences.general.startHidden=Itago ang window kapag sinimulan ang Cryptomator
preferences.general.autoCloseVaults=Awtomatikong i-lock ang mga bukas na vault kapag huminto sa aplikasyon
preferences.general.debugLogging=Paganahin ang pag-log ng debug preferences.general.debugLogging=Paganahin ang pag-log ng debug
preferences.general.debugDirectory=Magbunyag ng mga log file preferences.general.debugDirectory=Magbunyag ng mga log file
preferences.general.autoStart=Ilunsad ang Cryptomator sa pagsisimula ng system preferences.general.autoStart=Ilunsad ang Cryptomator sa pagsisimula ng system
@@ -410,7 +410,6 @@ main.vaultDetail.stats=Mga Istatistika ng Vault
main.vaultDetail.locateEncryptedFileBtn=Hanapin ang Naka-encrypt na File main.vaultDetail.locateEncryptedFileBtn=Hanapin ang Naka-encrypt na File
main.vaultDetail.locateEncryptedFileBtn.tooltip=Pumili ng file mula sa iyong vault upang mahanap ang naka-encrypt na katapat nito main.vaultDetail.locateEncryptedFileBtn.tooltip=Pumili ng file mula sa iyong vault upang mahanap ang naka-encrypt na katapat nito
main.vaultDetail.encryptedPathsCopied=Mga Path na Nakopya sa Clipboard! main.vaultDetail.encryptedPathsCopied=Mga Path na Nakopya sa Clipboard!
main.vaultDetail.filePickerTitle=Piliin ang File Inside Vault
### Missing ### Missing
main.vaultDetail.missing.info=Hindi makahanap ng vault ang Cryptomator sa landas na ito. main.vaultDetail.missing.info=Hindi makahanap ng vault ang Cryptomator sa landas na ito.
main.vaultDetail.missing.recheck=Suriin muli main.vaultDetail.missing.recheck=Suriin muli
@@ -560,4 +559,10 @@ shareVault.hub.message=Paano ibahagi ang Hub vault
shareVault.hub.description=Upang maibahagi ang nilalaman ng vault sa isa pang miyembro ng koponan, kailangan mong magsagawa ng dalawang hakbang: shareVault.hub.description=Upang maibahagi ang nilalaman ng vault sa isa pang miyembro ng koponan, kailangan mong magsagawa ng dalawang hakbang:
shareVault.hub.instruction.1=1. Ibahagi ang access ng naka-encrypt na folder ng vault sa pamamagitan ng cloud storage. shareVault.hub.instruction.1=1. Ibahagi ang access ng naka-encrypt na folder ng vault sa pamamagitan ng cloud storage.
shareVault.hub.instruction.2=2. Magbigay ng access sa miyembro ng team sa Cryptomator Hub. shareVault.hub.instruction.2=2. Magbigay ng access sa miyembro ng team sa Cryptomator Hub.
shareVault.hub.openHub=Buksan ang Cryptomator Hub shareVault.hub.openHub=Buksan ang Cryptomator Hub
# Decrypt File Names
# Event View
## event list entries
+46 -4
View File
@@ -1,6 +1,7 @@
# Locale Specific CSS files such as CJK, RTL,... # Locale Specific CSS files such as CJK, RTL,...
# Generics # Generics
generic.action.dismiss=Ignorer
## Button ## Button
generic.button.apply=Appliquer generic.button.apply=Appliquer
generic.button.back=Précédent generic.button.back=Précédent
@@ -282,7 +283,7 @@ preferences.title=Préférences
## General ## General
preferences.general=Général preferences.general=Général
preferences.general.startHidden=Démarrer Cryptomator en mode caché preferences.general.startHidden=Démarrer Cryptomator en mode caché
preferences.general.autoCloseVaults=Verrouiller automatiquement les coffres ouverts en quittant l'application preferences.general.autoCloseVaults=Verrouiller les coffres sans confirmation lors de la fermeture de l'application
preferences.general.debugLogging=Activer les logs debug preferences.general.debugLogging=Activer les logs debug
preferences.general.debugDirectory=Afficher le journal preferences.general.debugDirectory=Afficher le journal
preferences.general.autoStart=Lancer Cryptomator au démarrage du système preferences.general.autoStart=Lancer Cryptomator au démarrage du système
@@ -342,7 +343,7 @@ preferences.contribute.sponsor=Parrain
### Remove License Key Dialog ### Remove License Key Dialog
removeCert.title=Supprimer le certificat removeCert.title=Supprimer le certificat
removeCert.message=Supprimer le certificat de soutien ? removeCert.message=Supprimer le certificat de soutien ?
removeCert.description= removeCert.description=Les fonctionnalités principales de Cryptomator ne sont pas affectées par cela. L'accès à vos coffres n'est pas restreint et le niveau de sécurité n'est pas diminué.
#<-- Add entries for donations and code/translation/documentation contribution --> #<-- Add entries for donations and code/translation/documentation contribution -->
## About ## About
@@ -394,6 +395,7 @@ main.vaultlist.contextMenu.vaultoptions=Afficher les options du volume chiffré
main.vaultlist.contextMenu.reveal=Afficher le lecteur main.vaultlist.contextMenu.reveal=Afficher le lecteur
main.vaultlist.addVaultBtn.menuItemNew=Créer un nouveau coffre... main.vaultlist.addVaultBtn.menuItemNew=Créer un nouveau coffre...
main.vaultlist.addVaultBtn.menuItemExisting=Ouvrir un coffre existant... main.vaultlist.addVaultBtn.menuItemExisting=Ouvrir un coffre existant...
main.vaultlist.showEventsButton.tooltip=Ouvrir la vue Événements
##Notificaition ##Notificaition
main.notification.updateAvailable=Mise à jour disponible. main.notification.updateAvailable=Mise à jour disponible.
main.notification.support=Soutenir Cryptomator. main.notification.support=Soutenir Cryptomator.
@@ -422,7 +424,9 @@ main.vaultDetail.stats=Statistiques du volume chiffré
main.vaultDetail.locateEncryptedFileBtn=Localiser le fichier chiffré main.vaultDetail.locateEncryptedFileBtn=Localiser le fichier chiffré
main.vaultDetail.locateEncryptedFileBtn.tooltip=Choisissez un fichier dans votre coffre pour localiser sa version chiffrée main.vaultDetail.locateEncryptedFileBtn.tooltip=Choisissez un fichier dans votre coffre pour localiser sa version chiffrée
main.vaultDetail.encryptedPathsCopied=Chemins d'accès copiés dans le presse-papier ! main.vaultDetail.encryptedPathsCopied=Chemins d'accès copiés dans le presse-papier !
main.vaultDetail.filePickerTitle=Sélectionner le fichier dans le coffre main.vaultDetail.locateEncrypted.filePickerTitle=Sélectionner le fichier dans le coffre
main.vaultDetail.decryptName.buttonLabel=Déchiffrer le nom d'un fichier
main.vaultDetail.decryptName.tooltip=Choisir un fichier de coffre chiffré pour déchiffrer son nom
### Missing ### Missing
main.vaultDetail.missing.info=Cryptomator n'a pas pu trouver de volume chiffré dans ce chemin d'accès. main.vaultDetail.missing.info=Cryptomator n'a pas pu trouver de volume chiffré dans ce chemin d'accès.
main.vaultDetail.missing.recheck=Revérifier main.vaultDetail.missing.recheck=Revérifier
@@ -576,4 +580,42 @@ shareVault.hub.message=Comment partager un coffre central
shareVault.hub.description=Afin de partager le contenu du coffre avec un autre membre de l'équipe, vous devez effectuer deux étapes : shareVault.hub.description=Afin de partager le contenu du coffre avec un autre membre de l'équipe, vous devez effectuer deux étapes :
shareVault.hub.instruction.1=1. Partagez l'accès du dossier de coffre chiffré via le stockage cloud. shareVault.hub.instruction.1=1. Partagez l'accès du dossier de coffre chiffré via le stockage cloud.
shareVault.hub.instruction.2=2. Accorder l'accès au membre de l'équipe dans Cryptomator Hub. shareVault.hub.instruction.2=2. Accorder l'accès au membre de l'équipe dans Cryptomator Hub.
shareVault.hub.openHub=Ouvrir le Hub Cryptomator shareVault.hub.openHub=Ouvrir le Hub Cryptomator
# Decrypt File Names
decryptNames.title=Déchiffrer les noms de fichiers
decryptNames.filePicker.title=Sélectionner le fichier chiffré
decryptNames.filePicker.extensionDescription=Fichier chiffré Cryptomator
decryptNames.copyTable.tooltip=Copier le tableau
decryptNames.clearTable.tooltip=Effacer le tableau
decryptNames.copyHint=Copier le contenu de la cellule avec %s
decryptNames.dropZone.message=Déposer des fichiers ou cliquer pour en sélectionner
decryptNames.dropZone.error.foreignFiles=Les fichiers n'appartiennent pas au coffre « %s »
decryptNames.dropZone.error.noDirIdBackup=Le répertoire des fichiers sélectionnés ne contient pas de fichier dirId.c9r
decryptNames.dropZone.error.generic=Impossible de déchiffrer les noms de fichiers
# Event View
eventView.title=Événements
eventView.filter.allVaults=Tous
eventView.clearListButton.tooltip=Effacer la liste
## event list entries
eventView.entry.vaultLocked.description=Déverrouillez "%s" pour plus de détails
eventView.entry.conflictResolved.message=Conflit résolu
eventView.entry.conflictResolved.showDecrypted=Afficher le fichier déchiffré
eventView.entry.conflictResolved.copyDecrypted=Copier le chemin déchiffré
eventView.entry.conflict.message=La résolution des conflits a échoué
eventView.entry.conflict.showDecrypted=Afficher le fichier original déchiffré
eventView.entry.conflict.copyDecrypted=Copier le chemin original déchiffré
eventView.entry.conflict.showEncrypted=Afficher le fichier chiffré en conflit
eventView.entry.conflict.copyEncrypted=Copier le chemin chiffré en conflit
eventView.entry.decryptionFailed.message=Le déchiffrement a échoué
eventView.entry.decryptionFailed.showEncrypted=Afficher le fichier chiffré
eventView.entry.decryptionFailed.copyEncrypted=Copier le chemin chiffré
eventView.entry.brokenDirFile.message=Lien de répertoire cassé
eventView.entry.brokenDirFile.showEncrypted=Afficher le lien chiffré cassé
eventView.entry.brokenDirFile.copyEncrypted=Copier le chemin du lien cassé
eventView.entry.brokenFileNode.message=Nœud de système de fichiers cassé
eventView.entry.brokenFileNode.showEncrypted=Afficher le nœud chiffré cassé
eventView.entry.brokenFileNode.copyEncrypted=Copier le chemin du nœud chiffré cassé
eventView.entry.brokenFileNode.copyDecrypted=Copier le chemin déchiffré
@@ -135,3 +135,10 @@ lock.forced.retryBtn=Tentar de novo
#Retry If Readonly #Retry If Readonly
# Share Vault # Share Vault
# Decrypt File Names
# Event View
## event list entries
@@ -1,6 +1,7 @@
# Locale Specific CSS files such as CJK, RTL,... # Locale Specific CSS files such as CJK, RTL,...
# Generics # Generics
generic.action.dismiss=שחרור
## Button ## Button
generic.button.apply=החל generic.button.apply=החל
generic.button.back=חזור generic.button.back=חזור
@@ -48,6 +49,7 @@ addvaultwizard.new.nameInstruction=בחירת שם עבור הכספת
addvaultwizard.new.namePrompt=שם הכספת addvaultwizard.new.namePrompt=שם הכספת
### Location ### Location
addvaultwizard.new.locationInstruction=היכן Cryptomator צריך לשמור את הקבצים המוצפנים של הכספת שלך? addvaultwizard.new.locationInstruction=היכן Cryptomator צריך לשמור את הקבצים המוצפנים של הכספת שלך?
addvaultwizard.new.locationLoading=בודק מערכת קבצים מקומית עבור ספריות ברירת מחדל לאחסון ענן…
addvaultwizard.new.locationLabel=מיקום אחסון addvaultwizard.new.locationLabel=מיקום אחסון
addvaultwizard.new.locationPrompt= addvaultwizard.new.locationPrompt=
addvaultwizard.new.directoryPickerLabel=מיקום מותאם אישית addvaultwizard.new.directoryPickerLabel=מיקום מותאם אישית
@@ -260,7 +262,6 @@ preferences.title=העדפות
## General ## General
preferences.general=כללי preferences.general=כללי
preferences.general.startHidden=הסתר את החלון בהפעלת Cryptomator preferences.general.startHidden=הסתר את החלון בהפעלת Cryptomator
preferences.general.autoCloseVaults=נעל vaults פתוחים באופן אוטומטי בעת יציאה מהאפליקציה
preferences.general.debugLogging=אפשר רישום יומן באגים preferences.general.debugLogging=אפשר רישום יומן באגים
preferences.general.debugDirectory=הצג קבצי יומן preferences.general.debugDirectory=הצג קבצי יומן
preferences.general.autoStart=הפעלת Cryptomator עם הפעלת המערכת preferences.general.autoStart=הפעלת Cryptomator עם הפעלת המערכת
@@ -378,7 +379,6 @@ main.vaultDetail.stats=סטטיסטיקת הכספת
main.vaultDetail.locateEncryptedFileBtn=מצא קבצים מוצפנים main.vaultDetail.locateEncryptedFileBtn=מצא קבצים מוצפנים
main.vaultDetail.locateEncryptedFileBtn.tooltip=בחר קובץ מהכספת שלך על מנת לאתר את הקובץ התואם המוצפן main.vaultDetail.locateEncryptedFileBtn.tooltip=בחר קובץ מהכספת שלך על מנת לאתר את הקובץ התואם המוצפן
main.vaultDetail.encryptedPathsCopied=הנתיבים הועתקו ללוח! main.vaultDetail.encryptedPathsCopied=הנתיבים הועתקו ללוח!
main.vaultDetail.filePickerTitle=בחר קובץ בתוך הכספת
### Missing ### Missing
main.vaultDetail.missing.info=Cryptomator לא הצליח למצוא כספת בנתיב זה. main.vaultDetail.missing.info=Cryptomator לא הצליח למצוא כספת בנתיב זה.
main.vaultDetail.missing.recheck=בדיקה נוספת main.vaultDetail.missing.recheck=בדיקה נוספת
@@ -494,3 +494,10 @@ dokanySupportEnd.preferencesBtn=פתח העדפות
#Retry If Readonly #Retry If Readonly
# Share Vault # Share Vault
# Decrypt File Names
# Event View
## event list entries
@@ -1,6 +1,7 @@
# Locale Specific CSS files such as CJK, RTL,... # Locale Specific CSS files such as CJK, RTL,...
# Generics # Generics
generic.action.dismiss=खारिज करें
## Button ## Button
generic.button.apply=लागू करें generic.button.apply=लागू करें
generic.button.back=पीछे जाएं generic.button.back=पीछे जाएं
@@ -199,7 +200,6 @@ health.result.severityFilter.crit=गंभीर
preferences.title=प्राथमिकताएं preferences.title=प्राथमिकताएं
## General ## General
preferences.general=सामान्य preferences.general=सामान्य
preferences.general.autoCloseVaults=एप्लीकेशन बंद करते समय खुली हुई वॉल्ट्स को अपने आप लॉक करें
preferences.general.autoStart=क्रिप्टोमेटर को सिस्टम स्टार्ट पे खोले preferences.general.autoStart=क्रिप्टोमेटर को सिस्टम स्टार्ट पे खोले
## Interface ## Interface
preferences.interface.theme.automatic=ऑटोमैटिक preferences.interface.theme.automatic=ऑटोमैटिक
@@ -317,3 +317,10 @@ dokanySupportEnd.preferencesBtn=प्राथमिकताएँ खोल
#Retry If Readonly #Retry If Readonly
# Share Vault # Share Vault
# Decrypt File Names
# Event View
## event list entries
@@ -384,3 +384,10 @@ quit.lockAndQuitBtn=Zaključaj i napusti
#Retry If Readonly #Retry If Readonly
# Share Vault # Share Vault
# Decrypt File Names
# Event View
## event list entries
+14 -3
View File
@@ -1,6 +1,7 @@
# Locale Specific CSS files such as CJK, RTL,... # Locale Specific CSS files such as CJK, RTL,...
# Generics # Generics
generic.action.dismiss=Elvet
## Button ## Button
generic.button.apply=Alkalmaz generic.button.apply=Alkalmaz
generic.button.back=Vissza generic.button.back=Vissza
@@ -176,6 +177,7 @@ hub.registerFailed.description.generic=Hiba történt a regisztrációs folyamat
hub.registerFailed.description.deviceAlreadyExists=Ez az eszköz már egy másik felhasználóhoz van regisztrálva. Próbáljon meg felhasználói fiókot váltani, vagy használjon egy másik eszközt. hub.registerFailed.description.deviceAlreadyExists=Ez az eszköz már egy másik felhasználóhoz van regisztrálva. Próbáljon meg felhasználói fiókot váltani, vagy használjon egy másik eszközt.
### Unauthorized ### Unauthorized
hub.unauthorized.message=Hozzáférés megtagadva hub.unauthorized.message=Hozzáférés megtagadva
hub.unauthorized.description=Nincs hozzáférésed a széf megnyitásához. Vedd fel a kapcsolatot a széf tulajdonosával és kérj hozzáférést.
### Requires Account Initialization ### Requires Account Initialization
hub.requireAccountInit.message=Beavatkozás szükséges hub.requireAccountInit.message=Beavatkozás szükséges
hub.requireAccountInit.description.0=A folytatáshoz kérlek töltsd ki a szükséges lépéseket a te hub.requireAccountInit.description.0=A folytatáshoz kérlek töltsd ki a szükséges lépéseket a te
@@ -281,7 +283,7 @@ 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.autoCloseVaults=Széfek lezárása megerősítés nélkül 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
@@ -421,7 +423,6 @@ main.vaultDetail.stats=Széf statisztika
main.vaultDetail.locateEncryptedFileBtn=Titkosított fájl megkeresése 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.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.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
@@ -552,6 +553,10 @@ dokanySupportEnd.description=A Cryptomator nem támogatja tovább a Dokany köte
dokanySupportEnd.preferencesBtn=Beállítások megnyitása dokanySupportEnd.preferencesBtn=Beállítások megnyitása
#Retry If Readonly #Retry If Readonly
retryIfReadonly.title=Korlátozott Széf Hozzáférés
retryIfReadonly.message=Nincs írási jogod a széf könyvtárához
retryIfReadonly.description=A Cryptomator nem tud a széf könyvtárába írni. Átrakhatod a széfet írásvédettre és megpróbálhatod újra. Ezt az opciót kikapcsolhatod a széf beállításaiban.
retryIfReadonly.retry=Változtatás és Újrapróbálás
# Share Vault # Share Vault
shareVault.title=Széf megosztása shareVault.title=Széf megosztása
@@ -571,4 +576,10 @@ shareVault.hub.message=Hogyan osszon meg egy Hub széfet
shareVault.hub.description=Ahhoz, hogy megossza a széf tartalmát egy másik csapattaggal, két lépést kell végrehajtania: shareVault.hub.description=Ahhoz, hogy megossza a széf tartalmát egy másik csapattaggal, két lépést kell végrehajtania:
shareVault.hub.instruction.1=Ossza meg a titkosított széf mappájának hozzáférését felhőalapú tárolón keresztül. shareVault.hub.instruction.1=Ossza meg a titkosított széf mappájának hozzáférését felhőalapú tárolón keresztül.
shareVault.hub.instruction.2=2. Adjon hozzáférést a csapattagnak a Cryptomator Hubban. shareVault.hub.instruction.2=2. Adjon hozzáférést a csapattagnak a Cryptomator Hubban.
shareVault.hub.openHub=Nyissa meg a Cryptomator Hubot shareVault.hub.openHub=Nyissa meg a Cryptomator Hubot
# Decrypt File Names
# Event View
## event list entries
+37 -25
View File
@@ -1,6 +1,7 @@
# Locale Specific CSS files such as CJK, RTL,... # Locale Specific CSS files such as CJK, RTL,...
# Generics # Generics
generic.action.dismiss=Tutup
## Button ## Button
generic.button.apply=Terapkan generic.button.apply=Terapkan
generic.button.back=Kembali generic.button.back=Kembali
@@ -16,19 +17,19 @@ generic.button.print=Cetak
generic.button.remove=Hapus generic.button.remove=Hapus
# Error # Error
error.message=Terjadi kesalahan %s error.message=Terjadi kesalahan
error.description=Ups! Cryptomator tidak menyangka hal ini terjadi. Anda dapat mencari solusi yang tersedia untuk error ini. Atau jika error ini belum pernah dilaporkan, tidak perlu sungkan untuk melaporkannya. error.description=Ups! Cryptomator tidak menyangka hal ini terjadi. Anda dapat mencari solusi yang tersedia untuk error ini. Atau jika error ini belum pernah dilaporkan, tidak perlu sungkan untuk melaporkannya.
error.hyperlink.lookup=Cari tahu informasi lebih lanjut tentang suatu kesalahan error.hyperlink.lookup=Cari kesalahan ini
error.hyperlink.report=Laporkan error berikut error.hyperlink.report=Laporkan kesalahan ini
error.technicalDetails=Rincian: error.technicalDetails=Rincian:
error.existingSolutionDescription=Maaf, Cryptomator tiba-tiba berhenti. Tapi telah ditemukan sebuah jawaban untuk masalah ini. Lihat tautan berikut. error.existingSolutionDescription=Cryptomator tidak menyangka ini terjadi. Tapi telah ditemukan sebuah solusi untuk kesalahan ini. Lihat tautan berikut.
error.hyperlink.solution=Cari tahu solusi untuk masalah ini error.hyperlink.solution=Cari tahu solusinya
error.lookupPermissionMessage=Cryptomator bisa mencari solusinya secara daring. Ini akan meneruskan pesan ke direktori masalah kami dengan alamat IP Anda. error.lookupPermissionMessage=Cryptomator bisa mencari solusinya secara daring. Ini akan meneruskan pesan ke direktori masalah kami dengan alamat IP Anda.
error.dismiss=Tutup error.dismiss=Tutup
error.lookUpSolution=Cari tahu solusinya error.lookUpSolution=Cari tahu solusinya
# Defaults # Defaults
defaults.vault.vaultName=Brangkas defaults.vault.vaultName=Brankas
# Tray Menu # Tray Menu
traymenu.showMainWindow=Tampilkan traymenu.showMainWindow=Tampilkan
@@ -44,10 +45,10 @@ addvaultwizard.title=Tambah Brankas
## New ## New
addvaultwizard.new.title=Tambah Brankas Baru addvaultwizard.new.title=Tambah Brankas Baru
### Name ### Name
addvaultwizard.new.nameInstruction=Buat sebuah nama untuk brankas addvaultwizard.new.nameInstruction=Pilih sebuah nama untuk brankas
addvaultwizard.new.namePrompt=Nama Brankas addvaultwizard.new.namePrompt=Nama Brankas
### Location ### Location
addvaultwizard.new.locationInstruction=Dimana Cryptomator seharusnya menyimpan vault berisi file enkripsi Anda? addvaultwizard.new.locationInstruction=Di mana Cryptomator mesti menyimpan berkas terenkripsi dari brankas Anda?
addvaultwizard.new.locationLoading=Memeriksa sistem file lokal untuk direktori default penyimpanan cloud… addvaultwizard.new.locationLoading=Memeriksa sistem file lokal untuk direktori default penyimpanan cloud…
addvaultwizard.new.locationLabel=Lokasi penyimpanan addvaultwizard.new.locationLabel=Lokasi penyimpanan
addvaultwizard.new.locationPrompt= addvaultwizard.new.locationPrompt=
@@ -71,15 +72,15 @@ addvaultwizard.new.expertSettings.shorteningThreshold.tooltip=Buka dokumentasi u
addvaultwizard.new.expertSettings.shorteningThreshold.title=Panjang maksimum nama file terenkripsi addvaultwizard.new.expertSettings.shorteningThreshold.title=Panjang maksimum nama file terenkripsi
addvaultwizard.new.expertSettings.shorteningThreshold.valid=Valid addvaultwizard.new.expertSettings.shorteningThreshold.valid=Valid
### Password ### Password
addvaultwizard.new.createVaultBtn=Buat Brangkas addvaultwizard.new.createVaultBtn=Buat Brankas
addvaultwizard.new.generateRecoveryKeyChoice=Anda tidak dapat mengakses data tanpa kata sandi yang Anda miliki. Apa Anda ingin sebuah kunci pemulihan untuk berjaga-jaga jika seandainya Anda kehilangan kata sandi? addvaultwizard.new.generateRecoveryKeyChoice=Anda tidak dapat mengakses data tanpa kata sandi yang Anda miliki. Apa Anda ingin sebuah kunci pemulihan untuk berjaga-jaga jika seandainya Anda kehilangan kata sandi?
addvaultwizard.new.generateRecoveryKeyChoice.yes=Ya tolong, Lebih baik aman daripada menyesal addvaultwizard.new.generateRecoveryKeyChoice.yes=Ya tolong, Lebih baik aman daripada menyesal
addvaultwizard.new.generateRecoveryKeyChoice.no=Tidak terima kasih, Saya tidak akan kehilangan kata sandi saya addvaultwizard.new.generateRecoveryKeyChoice.no=Tidak terima kasih, Saya tidak akan kehilangan kata sandi saya
### Information ### Information
addvault.new.readme.storageLocation.fileName=PENTING.rtf addvault.new.readme.storageLocation.fileName=PENTING.rtf
addvault.new.readme.storageLocation.1=⚠️ FILE VAULT ⚠️ addvault.new.readme.storageLocation.1=⚠️ BERKAS BRANKAS ⚠️
addvault.new.readme.storageLocation.2=Ini adalah lokasi penyimpanan vault Anda. addvault.new.readme.storageLocation.2=Ini adalah lokasi penyimpanan brankas Anda.
addvault.new.readme.storageLocation.3=DILARANG addvault.new.readme.storageLocation.3=JANGAN
addvault.new.readme.storageLocation.4=• mengubah file apapun di direktori ini, atau addvault.new.readme.storageLocation.4=• mengubah file apapun di direktori ini, atau
addvault.new.readme.storageLocation.5=• menyalin file untuk dienkripsi ke dalam direktori ini. addvault.new.readme.storageLocation.5=• menyalin file untuk dienkripsi ke dalam direktori ini.
addvault.new.readme.storageLocation.6=Jika Anda ingin mengenkripsi file dan melihat isi konten dari vault, lakukan hal berikut: addvault.new.readme.storageLocation.6=Jika Anda ingin mengenkripsi file dan melihat isi konten dari vault, lakukan hal berikut:
@@ -97,15 +98,15 @@ addvaultwizard.existing.title=Tambahkan Vault yang Ada
addvaultwizard.existing.instruction=Pilih file "vault.cryptomator" Anda dari vault yang ada. Jika hanya ada file bernama "masterkey.cryptomator", pilih file tersebut. addvaultwizard.existing.instruction=Pilih file "vault.cryptomator" Anda dari vault yang ada. Jika hanya ada file bernama "masterkey.cryptomator", pilih file tersebut.
addvaultwizard.existing.chooseBtn=Pilih… addvaultwizard.existing.chooseBtn=Pilih…
addvaultwizard.existing.filePickerTitle=Pilih File Vault addvaultwizard.existing.filePickerTitle=Pilih File Vault
addvaultwizard.existing.filePickerMimeDesc=Vault Cryptomator addvaultwizard.existing.filePickerMimeDesc=Brankas Cryptomator
## Success ## Success
addvaultwizard.success.nextStepsInstructions=Vault "%s" telah dibuat.\nAnda harus membuka kunci vault ini untuk mengakses atau menambahkan konten. Anda juga dapat membuka kunci vault ini kapan saja di kemudian hari. addvaultwizard.success.nextStepsInstructions=Vault "%s" telah dibuat.\nAnda harus membuka kunci vault ini untuk mengakses atau menambahkan konten. Anda juga dapat membuka kunci vault ini kapan saja di kemudian hari.
addvaultwizard.success.unlockNow=Buka Kunci Sekarang addvaultwizard.success.unlockNow=Buka Kunci Sekarang
# Remove Vault # Remove Vault
removeVault.title=Hapus Vault removeVault.title=Hapus "%s"
removeVault.message=Hapus vault? removeVault.message=Hapus brankas?
removeVault.description=Tindakan ini hanya akan membuat Cryptomator melupakan vault ini. Anda dapat menambahkan vault ini lagi nanti. File yang telah dienkripsi tidak akan dihapus dari hard drive Anda. removeVault.description=Tindakan ini hanya akan membuat Cryptomator melupakan brankas ini. Anda dapat menambahkan brankas ini lagi nanti. Berkas yang telah dienkripsi tidak akan dihapus dari hard drive Anda.
# Change Password # Change Password
changepassword.title=Ubah Kata Sandi changepassword.title=Ubah Kata Sandi
@@ -124,14 +125,14 @@ unlock.passwordPrompt=Masukkan kata sandi "%s":
unlock.savePassword=Ingat Kata Sandi unlock.savePassword=Ingat Kata Sandi
unlock.unlockBtn=Buka Kunci unlock.unlockBtn=Buka Kunci
## Select ## Select
unlock.chooseMasterkey.message=File masterkey tidak ditemukan unlock.chooseMasterkey.message=Berkas masterkey tidak ditemukan
unlock.chooseMasterkey.description=Tidak dapat menemukan file masterkey untuk vault ini pada lokasi yang dicari. Mohon pilih file kunci secara manual. unlock.chooseMasterkey.description=Tidak dapat menemukan file masterkey untuk vault ini pada lokasi yang dicari. Mohon pilih file kunci secara manual.
unlock.chooseMasterkey.filePickerTitle=Pilih File Masterkey unlock.chooseMasterkey.filePickerTitle=Pilih File Masterkey
unlock.chooseMasterkey.filePickerMimeDesc=MasterKey Cryptomator unlock.chooseMasterkey.filePickerMimeDesc=MasterKey Cryptomator
## Success ## Success
unlock.success.message=Buka kunci berhasil unlock.success.message=Buka kunci berhasil
unlock.success.description="%s" berhasil dibuka! Vault Anda sekarang dapat diakses melalui drive virtual. unlock.success.description="%s" berhasil dibuka! Vault Anda sekarang dapat diakses melalui drive virtual.
unlock.success.rememberChoice=Ingat pilihan saya, jangan perlihatkan lagi unlock.success.rememberChoice=Ingat pilihan saya, jangan tanyakan lagi
unlock.success.revealBtn=Tampilkan Drive unlock.success.revealBtn=Tampilkan Drive
## Failure ## Failure
unlock.error.customPath.message=Tidak dapat memasang vault ke path kustom unlock.error.customPath.message=Tidak dapat memasang vault ke path kustom
@@ -142,7 +143,7 @@ unlock.error.customPath.description.hideawayNotDir=File sementara dan tersembuny
unlock.error.customPath.description.couldNotBeCleaned=Vault Anda tidak dapat dipasang ke path "%s". Silakan coba lagi atau pilih path yang berbeda. unlock.error.customPath.description.couldNotBeCleaned=Vault Anda tidak dapat dipasang ke path "%s". Silakan coba lagi atau pilih path yang berbeda.
unlock.error.customPath.description.notEmptyDir=Path kustom pemasangan "%s" bukan folder kosong. Silakan pilih folder kosong dan coba lagi. unlock.error.customPath.description.notEmptyDir=Path kustom pemasangan "%s" bukan folder kosong. Silakan pilih folder kosong dan coba lagi.
unlock.error.customPath.description.generic=Anda telah memilih kustom path pemasangan untuk vault ini, tetapi gagal menggunakannya dengan pesan:%2$s unlock.error.customPath.description.generic=Anda telah memilih kustom path pemasangan untuk vault ini, tetapi gagal menggunakannya dengan pesan:%2$s
unlock.error.restartRequired.message=Tidak dapat membuka kunci vault unlock.error.restartRequired.message=Tidak dapat membuka kunci brankas
unlock.error.restartRequired.description=Ubah jenis volume di opsi vault atau restart Cryptomator. unlock.error.restartRequired.description=Ubah jenis volume di opsi vault atau restart Cryptomator.
unlock.error.title=Gagal membuka kunci "%s" unlock.error.title=Gagal membuka kunci "%s"
## Hub ## Hub
@@ -154,7 +155,7 @@ hub.auth.message=Menunggu otentikasi…
hub.auth.description=Anda secara otomatis akan diarahkan ke halaman login. hub.auth.description=Anda secara otomatis akan diarahkan ke halaman login.
hub.auth.loginLink=Tidak diarahkan? Klik di sini untuk membukanya. hub.auth.loginLink=Tidak diarahkan? Klik di sini untuk membukanya.
### Receive Key ### Receive Key
hub.receive.message=Respons pemrosesan hub.receive.message=Memroses respons
hub.receive.description=Cryptomator menerima dan memproses respons dari Hub. Harap tunggu. hub.receive.description=Cryptomator menerima dan memproses respons dari Hub. Harap tunggu.
### Register Device ### Register Device
hub.register.message=Perangkat Baru hub.register.message=Perangkat Baru
@@ -176,10 +177,11 @@ hub.registerFailed.description.generic=Kesalahan terjadi dalam proses pendaftara
hub.registerFailed.description.deviceAlreadyExists=Perangkat ini sudah terdaftar untuk pengguna lain. Cobalah menggunakan akun pengguna atau perangkat yang berbeda. hub.registerFailed.description.deviceAlreadyExists=Perangkat ini sudah terdaftar untuk pengguna lain. Cobalah menggunakan akun pengguna atau perangkat yang berbeda.
### Unauthorized ### Unauthorized
hub.unauthorized.message=Akses ditolak hub.unauthorized.message=Akses ditolak
hub.unauthorized.description=Anda tidak punya otorisasi untuk membuka brankas ini. Hubungi pemilik brankas untuk meminta akses.
### Requires Account Initialization ### Requires Account Initialization
hub.requireAccountInit.message=Tindakan diperlukan hub.requireAccountInit.message=Tindakan diperlukan
hub.requireAccountInit.description.0=Untuk melanjutkan, silakan lengkapi langkah-langkah yang diperlukan hub.requireAccountInit.description.0=Untuk melanjutkan, silakan lengkapi langkah-langkah yang diperlukan dalam
hub.requireAccountInit.description.1=Hub profil pengguna hub.requireAccountInit.description.1=Profil pengguna Hub Anda
hub.requireAccountInit.description.2=. hub.requireAccountInit.description.2=.
### License Exceeded ### License Exceeded
hub.invalidLicense.message=Lisensi Hub tidak valid hub.invalidLicense.message=Lisensi Hub tidak valid
@@ -281,7 +283,7 @@ preferences.title=Preferensi
## General ## General
preferences.general=Umum preferences.general=Umum
preferences.general.startHidden=Sembunyikan jendela saat memulai Cryptomator preferences.general.startHidden=Sembunyikan jendela saat memulai Cryptomator
preferences.general.autoCloseVaults=Kunci vault yang terbuka secara otomatis saat aplikasi dihentikan preferences.general.autoCloseVaults=Kunci brankas tanpa bertanya ketika keluar aplikasi
preferences.general.debugLogging=Aktifkan pencatatan debug preferences.general.debugLogging=Aktifkan pencatatan debug
preferences.general.debugDirectory=Perlihatkan file log preferences.general.debugDirectory=Perlihatkan file log
preferences.general.autoStart=Jalankan Cryptomator saat sistem dimulai preferences.general.autoStart=Jalankan Cryptomator saat sistem dimulai
@@ -421,7 +423,6 @@ main.vaultDetail.stats=Statistik Vault
main.vaultDetail.locateEncryptedFileBtn=Temukan File yang Dienkripsi main.vaultDetail.locateEncryptedFileBtn=Temukan File yang Dienkripsi
main.vaultDetail.locateEncryptedFileBtn.tooltip=Pilih file dari vault Anda untuk menemukan mitra enkripsinya main.vaultDetail.locateEncryptedFileBtn.tooltip=Pilih file dari vault Anda untuk menemukan mitra enkripsinya
main.vaultDetail.encryptedPathsCopied=Path Disalin ke Clipboard! main.vaultDetail.encryptedPathsCopied=Path Disalin ke Clipboard!
main.vaultDetail.filePickerTitle=Pilih File Didalam Vault
### Missing ### Missing
main.vaultDetail.missing.info=Cryptomator tidak dapat menemukan vault di path ini. main.vaultDetail.missing.info=Cryptomator tidak dapat menemukan vault di path ini.
main.vaultDetail.missing.recheck=Periksa kembali main.vaultDetail.missing.recheck=Periksa kembali
@@ -552,6 +553,10 @@ dokanySupportEnd.description=Volume berjenis Dokany sudah tidak didukung oleh Cr
dokanySupportEnd.preferencesBtn=Buka Preferensi dokanySupportEnd.preferencesBtn=Buka Preferensi
#Retry If Readonly #Retry If Readonly
retryIfReadonly.title=Akses Brankas Dibatasi
retryIfReadonly.message=Tidak ada akses tulis ke direktori brankas
retryIfReadonly.description=Cryptomator tidak bisa menulis ke direktori brankas. Anda dapat mengubah brankas menjadi hanya-baca dan mencoba lagi. Opsi ini bisa dimatikan dalam opsi brankas.
retryIfReadonly.retry=Ubah dan Coba Lagi
# Share Vault # Share Vault
shareVault.title=Bagikan Vault shareVault.title=Bagikan Vault
@@ -571,4 +576,11 @@ shareVault.hub.message=Cara berbagi Hub vault
shareVault.hub.description=Untuk berbagi isi vault dengan anggota tim lain, Anda harus melakukan dua langkah: shareVault.hub.description=Untuk berbagi isi vault dengan anggota tim lain, Anda harus melakukan dua langkah:
shareVault.hub.instruction.1=1. Bagikan akses folder vault terenkripsi melalui penyimpanan cloud. shareVault.hub.instruction.1=1. Bagikan akses folder vault terenkripsi melalui penyimpanan cloud.
shareVault.hub.instruction.2=2. Berikan akses ke anggota tim di Cryptomator Hub. shareVault.hub.instruction.2=2. Berikan akses ke anggota tim di Cryptomator Hub.
shareVault.hub.openHub=Buka Cryptomator Hub shareVault.hub.openHub=Buka Cryptomator Hub
# Decrypt File Names
# Event View
eventView.filter.allVaults=Semua
## event list entries
+46 -3
View File
@@ -1,6 +1,7 @@
# Locale Specific CSS files such as CJK, RTL,... # Locale Specific CSS files such as CJK, RTL,...
# Generics # Generics
generic.action.dismiss=Ignora
## Button ## Button
generic.button.apply=Applica generic.button.apply=Applica
generic.button.back=Indietro generic.button.back=Indietro
@@ -282,7 +283,7 @@ preferences.title=Preferenze
## General ## General
preferences.general=Generale preferences.general=Generale
preferences.general.startHidden=Nascondi la finestra avviando Cryptomator preferences.general.startHidden=Nascondi la finestra avviando Cryptomator
preferences.general.autoCloseVaults=Blocca automaticamente le cassaforti aperte all'uscita dell'applicazione preferences.general.autoCloseVaults=Alla chiusura dell'applicazione blocca le casseforti senza chiedere conferma
preferences.general.debugLogging=Abilita la registrazione di debug preferences.general.debugLogging=Abilita la registrazione di debug
preferences.general.debugDirectory=Rivela i file di registro preferences.general.debugDirectory=Rivela i file di registro
preferences.general.autoStart=Avvia Cryptomator all'avvio del sistema preferences.general.autoStart=Avvia Cryptomator all'avvio del sistema
@@ -394,6 +395,7 @@ main.vaultlist.contextMenu.vaultoptions=Mostra le Opzioni della Cassaforte
main.vaultlist.contextMenu.reveal=Rivela Unità main.vaultlist.contextMenu.reveal=Rivela Unità
main.vaultlist.addVaultBtn.menuItemNew=Crea una nuova cassaforte... main.vaultlist.addVaultBtn.menuItemNew=Crea una nuova cassaforte...
main.vaultlist.addVaultBtn.menuItemExisting=Apri una cassaforte esistente... main.vaultlist.addVaultBtn.menuItemExisting=Apri una cassaforte esistente...
main.vaultlist.showEventsButton.tooltip=Apri vista eventi
##Notificaition ##Notificaition
main.notification.updateAvailable=Aggiornamento disponibile. main.notification.updateAvailable=Aggiornamento disponibile.
main.notification.support=Supporta Cryptomator. main.notification.support=Supporta Cryptomator.
@@ -422,7 +424,9 @@ main.vaultDetail.stats=Statistiche della Cassaforte
main.vaultDetail.locateEncryptedFileBtn=Individua File Crittografato main.vaultDetail.locateEncryptedFileBtn=Individua File Crittografato
main.vaultDetail.locateEncryptedFileBtn.tooltip=Scegli un file dalla cassaforte per individuare la controparte cifrata main.vaultDetail.locateEncryptedFileBtn.tooltip=Scegli un file dalla cassaforte per individuare la controparte cifrata
main.vaultDetail.encryptedPathsCopied=Percorsi copiati negli Appunti! main.vaultDetail.encryptedPathsCopied=Percorsi copiati negli Appunti!
main.vaultDetail.filePickerTitle=Seleziona File Nella Cassaforte main.vaultDetail.locateEncrypted.filePickerTitle=Seleziona file nella cassaforte
main.vaultDetail.decryptName.buttonLabel=Decifra nome file
main.vaultDetail.decryptName.tooltip=Seleziona il file di una cassaforte cifrata per decifrarne il nome
### Missing ### Missing
main.vaultDetail.missing.info=Cryptomator non è riuscito a trovare una cassaforte in questo percorso. main.vaultDetail.missing.info=Cryptomator non è riuscito a trovare una cassaforte in questo percorso.
main.vaultDetail.missing.recheck=Ricontrolla main.vaultDetail.missing.recheck=Ricontrolla
@@ -576,4 +580,43 @@ shareVault.hub.message=Come condividere una cassaforte Hub
shareVault.hub.description=Per condividere il contenuto della cassaforte con un altro membro del gruppo, è necessario eseguire due passaggi: shareVault.hub.description=Per condividere il contenuto della cassaforte con un altro membro del gruppo, è necessario eseguire due passaggi:
shareVault.hub.instruction.1=1. Condividi l'accesso alla cartella della cassaforte crittografata tramite l'archiviazione cloud. shareVault.hub.instruction.1=1. Condividi l'accesso alla cartella della cassaforte crittografata tramite l'archiviazione cloud.
shareVault.hub.instruction.2=2. Concedi l'accesso ai membri del gruppo nell'Hub Cryptomator. shareVault.hub.instruction.2=2. Concedi l'accesso ai membri del gruppo nell'Hub Cryptomator.
shareVault.hub.openHub=Apri l'Hub Cryptomator shareVault.hub.openHub=Apri l'Hub Cryptomator
# Decrypt File Names
decryptNames.title=Decifra i nomi dei files
decryptNames.filePicker.title=Seleziona file criptato
decryptNames.filePicker.extensionDescription=File crittografato Cryptomator
decryptNames.copyTable.tooltip=Copia tabella
decryptNames.clearTable.tooltip=Cancella la tabella
decryptNames.copyHint=Copia il contenuto della cella con %s
decryptNames.dropZone.message=Trascina i file o fai clic per selezionare
decryptNames.dropZone.error.vaultInternalFiles=Hai selezionato file di casseforti con il nome non decifrabile
decryptNames.dropZone.error.foreignFiles=I file non appartengono alla cassaforte "%s"
decryptNames.dropZone.error.noDirIdBackup=La directory dei file selezionati non contiene il file dirId.c9r
decryptNames.dropZone.error.generic=Decifratura nomi file non riuscita
# Event View
eventView.title=Eventi
eventView.filter.allVaults=Tutti
eventView.clearListButton.tooltip=Cancella elenco
## event list entries
eventView.entry.vaultLocked.description=Sblocca "%s" per i dettagli
eventView.entry.conflictResolved.message=Conflitto risolto
eventView.entry.conflictResolved.showDecrypted=Mostra file decifrato
eventView.entry.conflictResolved.copyDecrypted=Copia percorso decriptato
eventView.entry.conflict.message=Risoluzione dei conflitti fallita
eventView.entry.conflict.showDecrypted=Mostra il file originale decifrato
eventView.entry.conflict.copyDecrypted=Copia il percorso originale decifrato
eventView.entry.conflict.showEncrypted=Mostra file cifrato in conflitto
eventView.entry.conflict.copyEncrypted=Copia il percorso cifrato in conflitto
eventView.entry.decryptionFailed.message=Decifratura fallita
eventView.entry.decryptionFailed.showEncrypted=Mostra file cifrato
eventView.entry.decryptionFailed.copyEncrypted=Copia percorso cifrato
eventView.entry.brokenDirFile.message=Collegamento directory errato
eventView.entry.brokenDirFile.showEncrypted=Visualizza il link cifrato errato
eventView.entry.brokenDirFile.copyEncrypted=Copia il percorso errato del file cifrato
eventView.entry.brokenFileNode.message=Nodo file errato
eventView.entry.brokenFileNode.showEncrypted=Visualizza il nodo file cifrato errato
eventView.entry.brokenFileNode.copyEncrypted=Copia il percorso errato del nodo file cifrato
eventView.entry.brokenFileNode.copyDecrypted=Copia il percorso decifrato
+35 -3
View File
@@ -1,6 +1,7 @@
# Locale Specific CSS files such as CJK, RTL,... # Locale Specific CSS files such as CJK, RTL,...
# Generics # Generics
generic.action.dismiss=閉じる
## Button ## Button
generic.button.apply=適用 generic.button.apply=適用
generic.button.back=戻る generic.button.back=戻る
@@ -176,6 +177,7 @@ hub.registerFailed.description.generic=登録中にエラーが発生しまし
hub.registerFailed.description.deviceAlreadyExists=このデバイスは既に別のユーザーに登録されています。ユーザーアカウントを変更するか、別のデバイスを使用してください。 hub.registerFailed.description.deviceAlreadyExists=このデバイスは既に別のユーザーに登録されています。ユーザーアカウントを変更するか、別のデバイスを使用してください。
### Unauthorized ### Unauthorized
hub.unauthorized.message=アクセスが拒否されました hub.unauthorized.message=アクセスが拒否されました
hub.unauthorized.description=この金庫を開く権限がありません。金庫の所有者からアクセス許可を貰って下さい。
### Requires Account Initialization ### Requires Account Initialization
hub.requireAccountInit.message=アクションが必要です hub.requireAccountInit.message=アクションが必要です
hub.requireAccountInit.description.0=続行するには以下のサイトで必要な手順を完了してください hub.requireAccountInit.description.0=続行するには以下のサイトで必要な手順を完了してください
@@ -281,7 +283,7 @@ preferences.title=環境設定
## General ## General
preferences.general=基本設定 preferences.general=基本設定
preferences.general.startHidden=Cryptomator を開始したときウィンドウを隠す preferences.general.startHidden=Cryptomator を開始したときウィンドウを隠す
preferences.general.autoCloseVaults=アプリケーション終了するときに自動的に開いている金庫を施錠する preferences.general.autoCloseVaults=アプリケーション終了時に質問せずに金庫をロックする
preferences.general.debugLogging=ログを有効にする preferences.general.debugLogging=ログを有効にする
preferences.general.debugDirectory=ログ ファイルを表示 preferences.general.debugDirectory=ログ ファイルを表示
preferences.general.autoStart=システム開始時に Cryptomator を起動する preferences.general.autoStart=システム開始時に Cryptomator を起動する
@@ -333,8 +335,12 @@ preferences.contribute.registeredFor=サポート証明書 (%s) が登録され
preferences.contribute.noCertificate=Cryptomator を支援し、サポーター証明書を受け取りましょう。ライセンスキーに似ていますがフリーソフトを使う寄付者向けのキーです。 ;-) preferences.contribute.noCertificate=Cryptomator を支援し、サポーター証明書を受け取りましょう。ライセンスキーに似ていますがフリーソフトを使う寄付者向けのキーです。 ;-)
preferences.contribute.getCertificate=まだ証明書を手に入れていませんか? 詳細はこちらから確認できます。 preferences.contribute.getCertificate=まだ証明書を手に入れていませんか? 詳細はこちらから確認できます。
preferences.contribute.promptText=サポーター証明書をここに張り付けてください preferences.contribute.promptText=サポーター証明書をここに張り付けてください
preferences.contribute.donate=寄付する
preferences.contribute.sponsor=スポンサー
### Remove License Key Dialog ### Remove License Key Dialog
removeCert.title=証明書を削除
removeCert.message=サポーター証明書を削除しますか?
#<-- Add entries for donations and code/translation/documentation contribution --> #<-- Add entries for donations and code/translation/documentation contribution -->
## About ## About
@@ -384,7 +390,11 @@ main.vaultlist.contextMenu.unlock=解錠...
main.vaultlist.contextMenu.unlockNow=今すぐ解錠 main.vaultlist.contextMenu.unlockNow=今すぐ解錠
main.vaultlist.contextMenu.vaultoptions=金庫のオプションを表示 main.vaultlist.contextMenu.vaultoptions=金庫のオプションを表示
main.vaultlist.contextMenu.reveal=ドライブを表示 main.vaultlist.contextMenu.reveal=ドライブを表示
main.vaultlist.addVaultBtn.menuItemNew=新しい金庫を作成…
main.vaultlist.addVaultBtn.menuItemExisting=既存の金庫を開く…
##Notificaition ##Notificaition
main.notification.updateAvailable=アップデートがあります。
main.notification.support=Cryptomator を支援する。
## Vault Detail ## Vault Detail
### Welcome ### Welcome
main.vaultDetail.welcomeOnboarding=ファイルを保護するために Cryptomator を選んでいただきありがとうございます。ヘルプが必要であれば、スタートガイドをご覧ください: main.vaultDetail.welcomeOnboarding=ファイルを保護するために Cryptomator を選んでいただきありがとうございます。ヘルプが必要であれば、スタートガイドをご覧ください:
@@ -410,7 +420,9 @@ main.vaultDetail.stats=金庫の統計情報
main.vaultDetail.locateEncryptedFileBtn=暗号化されたファイルの場所 main.vaultDetail.locateEncryptedFileBtn=暗号化されたファイルの場所
main.vaultDetail.locateEncryptedFileBtn.tooltip=暗号化された金庫のファイルを選択してください main.vaultDetail.locateEncryptedFileBtn.tooltip=暗号化された金庫のファイルを選択してください
main.vaultDetail.encryptedPathsCopied=パスをクリップボードにコピーしました! main.vaultDetail.encryptedPathsCopied=パスをクリップボードにコピーしました!
main.vaultDetail.filePickerTitle=金庫内のファイルを選択 main.vaultDetail.locateEncrypted.filePickerTitle=金庫内のファイルを選択
main.vaultDetail.decryptName.buttonLabel=ファイル名の復号化
main.vaultDetail.decryptName.tooltip=名前を復号化する暗号化金庫を選択してください
### Missing ### Missing
main.vaultDetail.missing.info=Cryptomator はこの場所に金庫を見つけることができませんでした。 main.vaultDetail.missing.info=Cryptomator はこの場所に金庫を見つけることができませんでした。
main.vaultDetail.missing.recheck=再確認 main.vaultDetail.missing.recheck=再確認
@@ -541,6 +553,9 @@ dokanySupportEnd.description=ボリュームタイプ
dokanySupportEnd.preferencesBtn=環境設定を開く dokanySupportEnd.preferencesBtn=環境設定を開く
#Retry If Readonly #Retry If Readonly
retryIfReadonly.title=制限された金庫へのアクセス
retryIfReadonly.message=金庫のディレクトリに書き込み権限がありません
retryIfReadonly.retry=変更して再試行
# Share Vault # Share Vault
shareVault.title=保管庫を共有する shareVault.title=保管庫を共有する
@@ -560,4 +575,21 @@ shareVault.hub.message=ハブ保管庫の共有方法
shareVault.hub.description=データ保管庫のコンテンツを他のチームメンバーと共有するには、2つの手順を実行する必要があります: shareVault.hub.description=データ保管庫のコンテンツを他のチームメンバーと共有するには、2つの手順を実行する必要があります:
shareVault.hub.instruction.1=1. クラウドストレージ経由で暗号化された保管庫フォルダへのアクセスを共有します。 shareVault.hub.instruction.1=1. クラウドストレージ経由で暗号化された保管庫フォルダへのアクセスを共有します。
shareVault.hub.instruction.2=2. Cryptomator Hubでチームメンバーにアクセスを許可する。 shareVault.hub.instruction.2=2. Cryptomator Hubでチームメンバーにアクセスを許可する。
shareVault.hub.openHub=Cryptomator Hubを開く shareVault.hub.openHub=Cryptomator Hubを開く
# Decrypt File Names
decryptNames.title=ファイル名の復号化
decryptNames.filePicker.title=暗号化されたファイルを選択
decryptNames.filePicker.extensionDescription=Cryptomator で暗号化したファイル
decryptNames.copyTable.tooltip=表をコピー
decryptNames.clearTable.tooltip=表をクリア
decryptNames.copyHint=%s でセルの内容をコピー
decryptNames.dropZone.message=ファイルをドロップまたはクリックして選択
decryptNames.dropZone.error.vaultInternalFiles=選択された金庫の内部ファイルに復号化できる名前がありません
decryptNames.dropZone.error.foreignFiles=ファイルは金庫 "%s" に属していません
decryptNames.dropZone.error.noDirIdBackup=選択したファイルのディレクトリにdirId.c9rファイルが含まれていません
decryptNames.dropZone.error.generic=ファイル名の復号化に失敗しました
# Event View
## event list entries

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