Преглед на файлове

Merge branch 'develop' into feature/restore-vaultconfig

Jan-Peter Klein преди 2 седмици
родител
ревизия
644e38f49e

+ 65 - 1
.github/workflows/appimage.yml

@@ -52,7 +52,6 @@ jobs:
           java-version: ${{ env.JAVA_VERSION }}
           check-latest: true
           cache: 'maven'
-
       - name: Download OpenJFX jmods
         id: download-jmods
         run: |
@@ -194,3 +193,68 @@ jobs:
             cryptomator-*.AppImage
             cryptomator-*.zsync
             cryptomator-*.asc
+
+  create-aur-bin-pr:
+    name: Create PR for aur-bin repo
+    needs: [build, get-version]
+    runs-on: ubuntu-latest
+    if: github.event_name == 'release'
+    steps:
+      - name: Download AppImages
+        uses: actions/download-artifact@v4
+        with:
+          path: downloads/
+          merge-multiple: true
+      - name: Compute sha256 hash of AppImages
+        id: checksums
+        run: |
+          X64_SHA256=$(sha256sum downloads/cryptomator-*-x86_64.AppImage | cut -d ' ' -f1)
+          echo "x64-sha256sum=${X64_SHA256}" >> "$GITHUB_OUTPUT"
+          AARCH64_SHA256=$(sha256sum downloads/cryptomator-*-aarch64.AppImage | cut -d ' ' -f1)
+          echo "aarch64-sha256sum=${AARCH64_SHA256}" >> "$GITHUB_OUTPUT"
+      - uses: actions/checkout@v4
+        with:
+          repository: 'cryptomator/aur-bin'
+          token: ${{ secrets.CRYPTOBOT_PR_TOKEN }}
+      - name: Install dependencies
+        run: |
+          sudo apt-get update
+          sudo apt-get -y install makepkg pacman-package-manager
+      - name: Checkout release branch
+        run: |
+          git checkout -b release/${{ needs.get-version.outputs.semVerStr }}
+      - name: Update build file
+        run: |
+          sed -i -e 's|^pkgver=.*$|pkgver=${{ needs.get-version.outputs.semVerStr }}|' PKGBUILD
+          sed -i -e 's|^pkgrel=.*$|pkgrel=1|' PKGBUILD
+          sed -i -e "s|^sha256sums_x86_64=.*$|sha256sums_x86_64=('${{ steps.checksums.outputs.x64-sha256sum }}'|" PKGBUILD
+          sed -i -e "s|^sha256sums_aarch64=.*$|sha256sums_aarch64=('${{ steps.checksums.outputs.aarch64-sha256sum}}'|" PKGBUILD
+          makepkg --printsrcinfo > .SRCINFO
+      - name: Commit and push
+        run: |
+          git config user.name "${{ github.actor }}"
+          git config user.email "${{ github.actor_id }}+${{ github.actor }}@users.noreply.github.com"
+          git config push.autoSetupRemote true
+          git stage .
+          git commit -m "Prepare release ${{needs.get-version.outputs.semVerStr}}"
+          git push
+      - name: Create pull request
+        id: create-pr
+        run: |
+          printf "> [!IMPORTANT]\n> Todos:\n> - [ ] Update build instructions\n> - [ ] Check for JDK update\n> - [ ] Check for JFX update" > pr_body.md
+          URL=$(gh pr create --title "Release ${{ needs.get-version.outputs.semVerStr }}" --body-file pr_body.md)
+          echo "PR_URL=$URL" >> "$GITHUB_OUTPUT"
+        env:
+          GH_TOKEN: ${{ secrets.CRYPTOBOT_PR_TOKEN }}
+      - name: Slack Notification
+        uses: rtCamp/action-slack-notify@v2
+        env:
+          SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }}
+          SLACK_USERNAME: 'Cryptobot'
+          SLACK_ICON: false
+          SLACK_ICON_EMOJI: ':bot:'
+          SLACK_CHANNEL: 'cryptomator-desktop'
+          SLACK_TITLE: "AUR-bin release PR for ${{ github.event.repository.name }} ${{ github.event.release.tag_name }} created."
+          SLACK_MESSAGE: "See <${{ steps.create-pr.outputs.PR_URL }}|PR> on how to proceed."
+          SLACK_FOOTER: false
+          MSG_MINIMAL: true

+ 93 - 0
.github/workflows/aur.yml

@@ -0,0 +1,93 @@
+name: Create PR for AUR
+
+on:
+  release:
+    types: [published]
+  workflow_dispatch:
+    inputs:
+      tag:
+        description: 'Release tag'
+        required: true
+
+jobs:
+  get-version:
+    uses: ./.github/workflows/get-version.yml
+    with:
+      version: ${{ inputs.tag }}
+  tarball:
+    name: Determines tarball url and compute checksum
+    runs-on: ubuntu-latest
+    needs: [get-version]
+    if:  github.event_name == 'workflow_dispatch' || needs.get-version.outputs.versionType == 'stable'
+    outputs:
+      url: ${{ steps.url.outputs.url}}
+      sha256: ${{ steps.sha256.outputs.sha256}}
+    steps:
+      - name: Determine tarball url
+        id: url
+        run: |
+          URL="";
+          if [[ -n "${{ inputs.tag }}"  ]]; then
+            URL="https://github.com/cryptomator/cryptomator/archive/refs/tags/${{ inputs.tag }}.tar.gz"
+          else
+            URL="https://github.com/cryptomator/cryptomator/archive/refs/tags/${{ github.event.release.tag_name }}.tar.gz"
+          fi
+          echo "url=${URL}" >> "$GITHUB_OUTPUT"
+      - name: Download source tarball and compute checksum
+        id: sha256
+        run: |
+          curl --silent --fail-with-body -L -H "Accept: application/vnd.github+json" ${{ steps.url.outputs.url }} --output cryptomator.tar.gz
+          TARBALL_SHA256=$(sha256sum cryptomator.tar.gz | cut -d ' ' -f1)
+          echo "sha256=${TARBALL_SHA256}" >> "$GITHUB_OUTPUT"
+  aur:
+    name: Create PR for AUR
+    runs-on: ubuntu-latest
+    needs: [tarball, get-version]
+    env:
+      AUR_PR_URL: tbd
+    steps:
+      - uses: actions/checkout@v4
+        with:
+          repository: 'cryptomator/aur'
+          token: ${{ secrets.CRYPTOBOT_PR_TOKEN }}
+      - name: Install dependencies
+        run: |
+          sudo apt-get update
+          sudo apt-get install makepkg pacman-package-manager
+      - name: Checkout release branch
+        run: |
+          git checkout -b release/${{ needs.get-version.outputs.semVerStr }}
+      - name: Update build file
+        run: |
+          sed -i -e 's|^pkgver=.*$|pkgver=${{ needs.get-version.outputs.semVerStr }}|' PKGBUILD
+          sed -i -e 's|^pkgrel=.*$|pkgrel=1|' PKGBUILD
+          sed -i -e "s|^sha256sums=.*$|sha256sums=('${{ needs.tarball.outputs.sha256 }}'|" PKGBUILD
+          makepkg --printsrcinfo > .SRCINFO
+      - name: Commit and push
+        run: |
+          git config user.name "${{ github.actor }}"
+          git config user.email "${{ github.actor_id }}+${{ github.actor }}@users.noreply.github.com"
+          git config push.autoSetupRemote true
+          git stage .
+          git commit -m "Prepare release ${{needs.get-version.outputs.semVerStr}}"
+          git push
+      - name: Create pull request
+        run: |
+          printf "> [!IMPORTANT]\n> Todos:\n> - [ ] Update build instructions\n> - [ ] Check for JDK update\n> - [ ] Check for JFX update" > pr_body.md
+          PR_URL=$(gh pr create --title "Release ${{ needs.get-version.outputs.semVerStr }}" --body-file pr_body.md)
+          echo "AUR_PR_URL=$PR_URL" >> "$GITHUB_ENV"
+        env:
+          GH_TOKEN: ${{ secrets.CRYPTOBOT_PR_TOKEN }}
+      - name: Slack Notification
+        uses: rtCamp/action-slack-notify@v2
+        if: github.event_name == 'release'
+        env:
+          SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }}
+          SLACK_USERNAME: 'Cryptobot'
+          SLACK_ICON: false
+          SLACK_ICON_EMOJI: ':bot:'
+          SLACK_CHANNEL: 'cryptomator-desktop'
+          SLACK_TITLE: "AUR release PR created for ${{ github.event.repository.name }} ${{ github.event.release.tag_name }} created."
+          SLACK_MESSAGE: "See <${{ env.AUR_PR_URL }}|PR> on how to proceed."
+          SLACK_FOOTER: false
+          MSG_MINIMAL: true

+ 2 - 2
.github/workflows/flathub.yml

@@ -49,7 +49,7 @@ jobs:
       - uses: actions/checkout@v4
         with:
           repository: 'flathub/org.cryptomator.Cryptomator'
-          token: ${{ secrets.CRYPTOBOT_WINGET_TOKEN }}
+          token: ${{ secrets.CRYPTOBOT_PR_TOKEN }}
       - name: Checkout release branch
         run: |
           git checkout -b release/${{ needs.get-version.outputs.semVerStr }}
@@ -72,7 +72,7 @@ jobs:
           PR_URL=$(gh pr create --title "Release ${{ needs.get-version.outputs.semVerStr }}" --body-file pr_body.md)
           echo "FLATHUB_PR_URL=$PR_URL" >> "$GITHUB_ENV"
         env:
-          GH_TOKEN: ${{ secrets.CRYPTOBOT_WINGET_TOKEN }}
+          GH_TOKEN: ${{ secrets.CRYPTOBOT_PR_TOKEN }}
       - name: Slack Notification
         uses: rtCamp/action-slack-notify@v2
         if: github.event_name == 'release'

+ 45 - 37
.github/workflows/win-exe.yml

@@ -12,6 +12,11 @@ on:
         description: 'Build debug version with console output'
         type: boolean
         default: false
+      sign:
+        description: 'Sign binaries'
+        required: false
+        type: boolean
+        default: false
   push:
     branches-ignore:
       - 'dependabot/**'
@@ -126,9 +131,6 @@ jobs:
           --no-man-pages
           --strip-debug
           --compress zip-0
-      - name: Change win-console flag if debug is active
-        if: ${{ inputs.isDebug }}
-        run: echo "WIN_CONSOLE_FLAG=--win-console" >> $GITHUB_ENV
       - name: Run jpackage
         run: >
           ${JAVA_HOME}/bin/jpackage
@@ -166,7 +168,7 @@ jobs:
           --java-options "-Djavafx.verbose=${{ inputs.isDebug }}"
           --resource-dir dist/win/resources
           --icon dist/win/resources/Cryptomator.ico
-          ${WIN_CONSOLE_FLAG}
+          --add-launcher "Cryptomator (Debug)=dist/win/debug-launcher.properties"
       - name: Patch Application Directory
         run: |
           cp dist/win/contrib/* appdir/Cryptomator
@@ -181,7 +183,9 @@ jobs:
             exit 1
           }
       - name: Fix permissions
-        run: attrib -r appdir/Cryptomator/Cryptomator.exe
+        run: |
+          attrib -r appdir/Cryptomator/Cryptomator.exe
+          attrib -r "appdir/Cryptomator/Cryptomator (Debug).exe"
         shell: pwsh
       - name: Extract jars with DLLs for Codesigning
         shell: pwsh
@@ -206,16 +210,17 @@ jobs:
           New-Item -Path appdir/jpackage-jmod -ItemType Directory
           & $env:JAVA_HOME\bin\jmod.exe extract --dir jpackage-jmod "${env:JAVA_HOME}\jmods\jdk.jpackage.jmod"
           Get-ChildItem -Recurse -Path "jpackage-jmod" -File wixhelper.dll | Select-Object -Last 1 | Copy-Item -Destination "appdir"
-      - name: Codesign
-        uses: skymatic/code-sign-action@v3
+      - name: Sign DLLs with Actalis CodeSigner
+        if: inputs.sign || github.event_name == 'release'
+        uses: skymatic/workflows/.github/actions/win-sign-action@450e322ff2214d0be0b079b63343c894f3ef735f
         with:
-          certificate: ${{ secrets.WIN_CODESIGN_P12_BASE64 }}
-          password: ${{ secrets.WIN_CODESIGN_P12_PW }}
-          certificatesha1: 5FC94CE149E5B511E621F53A060AC67CBD446B3A
-          description: Cryptomator
-          timestampUrl: 'http://timestamp.digicert.com'
-          folder: appdir
+          base-dir: 'appdir'
+          file-extensions: 'dll,exe,ps1'
           recursive: true
+          sign-description: 'Cryptomator'
+          sign-url: 'https://cryptomator.org'
+          username: ${{ secrets.WIN_CODESIGN_USERNAME }}
+          password: ${{ secrets.WIN_CODESIGN_PW }}
       - name: Replace DLLs inside jars with signed ones
         shell: pwsh
         run: |
@@ -264,15 +269,16 @@ jobs:
         env:
           JP_WIXWIZARD_RESOURCES: ${{ github.workspace }}/dist/win/resources # requires abs path, used in resources/main.wxs
           JP_WIXHELPER_DIR: ${{ github.workspace }}\appdir
-      - name: Codesign MSI
-        uses: skymatic/code-sign-action@v3
+      - name: Sign msi with Actalis CodeSigner
+        if: inputs.sign || github.event_name == 'release'
+        uses: skymatic/workflows/.github/actions/win-sign-action@450e322ff2214d0be0b079b63343c894f3ef735f
         with:
-          certificate: ${{ secrets.WIN_CODESIGN_P12_BASE64 }}
-          password: ${{ secrets.WIN_CODESIGN_P12_PW }}
-          certificatesha1: 5FC94CE149E5B511E621F53A060AC67CBD446B3A
-          description: Cryptomator Installer
-          timestampUrl: 'http://timestamp.digicert.com'
-          folder: installer
+          base-dir: 'installer'
+          file-extensions: 'msi'
+          sign-description: 'Cryptomator Installer'
+          sign-url: 'https://cryptomator.org'
+          username: ${{ secrets.WIN_CODESIGN_USERNAME }}
+          password: ${{ secrets.WIN_CODESIGN_PW }}
       - name: Add possible alpha/beta tags and architecture to installer name
         run: mv installer/Cryptomator-*.msi Cryptomator-${{ needs.get-version.outputs.semVerStr }}-${{ matrix.arch }}.msi
       - name: Create detached GPG signature with key 615D449FE6E6A235
@@ -375,27 +381,29 @@ jobs:
       - name: Detach burn engine in preparation to sign
         run: >
           wix burn detach installer/unsigned/Cryptomator-Installer.exe -engine tmp/engine.exe
-      - name: Codesign burn engine
-        uses: skymatic/code-sign-action@v3
+      - name: Sign burn engine with Actalis CodeSigner
+        if: inputs.sign || github.event_name == 'release'
+        uses: skymatic/workflows/.github/actions/win-sign-action@450e322ff2214d0be0b079b63343c894f3ef735f
         with:
-          certificate: ${{ secrets.WIN_CODESIGN_P12_BASE64 }}
-          password: ${{ secrets.WIN_CODESIGN_P12_PW }}
-          certificatesha1: 5FC94CE149E5B511E621F53A060AC67CBD446B3A
-          description: Cryptomator Installer
-          timestampUrl: 'http://timestamp.digicert.com'
-          folder: tmp
+          base-dir: 'tmp'
+          file-extensions: 'exe'
+          sign-description: 'Cryptomator Bundle Installer'
+          sign-url: 'https://cryptomator.org'
+          username: ${{ secrets.WIN_CODESIGN_USERNAME }}
+          password: ${{ secrets.WIN_CODESIGN_PW }}
       - name: Reattach signed burn engine to installer
         run: >
           wix burn reattach installer/unsigned/Cryptomator-Installer.exe -engine tmp/engine.exe -o installer/Cryptomator-Installer.exe
-      - name: Codesign EXE
-        uses: skymatic/code-sign-action@v3
+      - name: Sign installer with Actalis CodeSigner
+        if: inputs.sign || github.event_name == 'release'
+        uses: skymatic/workflows/.github/actions/win-sign-action@450e322ff2214d0be0b079b63343c894f3ef735f
         with:
-          certificate: ${{ secrets.WIN_CODESIGN_P12_BASE64 }}
-          password: ${{ secrets.WIN_CODESIGN_P12_PW }}
-          certificatesha1: 5FC94CE149E5B511E621F53A060AC67CBD446B3A
-          description: Cryptomator Installer
-          timestampUrl: 'http://timestamp.digicert.com'
-          folder: installer
+          base-dir: 'installer'
+          file-extensions: 'exe'
+          sign-description: 'Cryptomator Bundle Installer'
+          sign-url: 'https://cryptomator.org'
+          username: ${{ secrets.WIN_CODESIGN_USERNAME }}
+          password: ${{ secrets.WIN_CODESIGN_PW }}
       - name: Add possible alpha/beta tags to installer name
         run: mv installer/Cryptomator-Installer.exe Cryptomator-${{ needs.get-version.outputs.semVerStr }}-${{ matrix.executable-suffix }}.exe
       - name: Create detached GPG signature with key 615D449FE6E6A235

+ 2 - 2
.github/workflows/winget.yml

@@ -16,7 +16,7 @@ jobs:
         run: |
           gh repo sync cryptomator/winget-pkgs -b master --force
         env:
-          GH_TOKEN: ${{ secrets.CRYPTOBOT_WINGET_TOKEN }}
+          GH_TOKEN: ${{ secrets.CRYPTOBOT_PR_TOKEN }}
       - name: Submit package
         uses: vedantmgoyal2009/winget-releaser@main
         with:
@@ -24,4 +24,4 @@ jobs:
           version: ${{ inputs.tag }}
           release-tag: ${{ inputs.tag }}
           installers-regex: '-x64\.msi$'
-          token: ${{ secrets.CRYPTOBOT_WINGET_TOKEN }}
+          token: ${{ secrets.CRYPTOBOT_PR_TOKEN }}

+ 6 - 0
dist/linux/common/org.cryptomator.Cryptomator.metainfo.xml

@@ -83,6 +83,12 @@
 	</content_rating>
 
 	<releases>
+		<release date="2025-07-08" version="1.17.1">
+			<url type="details">https://github.com/cryptomator/cryptomator/releases/1.17.1</url>
+		</release>
+		<release date="2025-06-24" version="1.17.0">
+			<url type="details">https://github.com/cryptomator/cryptomator/releases/1.17.0</url>
+		</release>
 		<release date="2025-05-15" version="1.16.2">
 			<url type="details">https://github.com/cryptomator/cryptomator/releases/1.16.2</url>
 		</release>

+ 2 - 1
dist/win/.gitignore

@@ -4,7 +4,8 @@ installer
 *.wixobj
 *.pdb
 *.msi
+*Debug.properties
 *.exe
 *.jmod
 resources/jfxJmods.zip
-license.rtf
+license.rtf

+ 5 - 1
dist/win/build.bat

@@ -11,6 +11,10 @@ SET HELP_URL="https://cryptomator.org/contact/"
 SET MODULE_AND_MAIN_CLASS="org.cryptomator.desktop/org.cryptomator.launcher.Cryptomator"
 SET LOOPBACK_ALIAS="cryptomator-vault"
 
+:: read clean parameter from command line
+SET CLEAN=0
+IF "%~1"=="clean" SET CLEAN=1
+
 pwsh -NoLogo -NoProfile -ExecutionPolicy Unrestricted -Command .\build.ps1^
  -AppName %APPNAME%^
  -MainJarGlob "%MAIN_JAR_GLOB%"^
@@ -22,4 +26,4 @@ pwsh -NoLogo -NoProfile -ExecutionPolicy Unrestricted -Command .\build.ps1^
  -HelpUrl "%HELP_URL%"^
  -UpdateUrl "%UPDATE_URL%"^
  -LoopbackAlias "%LOOPBACK_ALIAS%"^
- -Clean 1
+ -Clean %CLEAN%

+ 64 - 32
dist/win/build.ps1

@@ -9,9 +9,15 @@ Param(
 	[Parameter(Mandatory, HelpMessage="Please provide an update url")][string] $UpdateUrl,
 	[Parameter(Mandatory, HelpMessage="Please provide an about url")][string] $AboutUrl,
 	[Parameter(Mandatory, HelpMessage="Please provide an alias for localhost")][string] $LoopbackAlias,
-	[bool] $clean
+	[bool] $clean = $false # if true, cleans up previous build artifacts
 )
 
+# ============================
+# Function Definitions Section
+# ============================
+
+function Main {
+
 [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
 $ProgressPreference = 'SilentlyContinue' # disables Invoke-WebRequest's progress bar, which slows down downloads to a few bytes/s
 
@@ -50,11 +56,11 @@ $version = $(mvn -f $buildDir/../../pom.xml help:evaluate -Dexpression="project.
 $semVerNo = $version -replace '(\d+\.\d+\.\d+).*','$1'
 $revisionNo = $(git rev-list --count HEAD)
 
-Write-Output "`$version=$version"
-Write-Output "`$semVerNo=$semVerNo"
-Write-Output "`$revisionNo=$revisionNo"
-Write-Output "`$buildDir=$buildDir"
-Write-Output "`$Env:JAVA_HOME=$Env:JAVA_HOME"
+Write-Host "`$version=$version"
+Write-Host "`$semVerNo=$semVerNo"
+Write-Host "`$revisionNo=$revisionNo"
+Write-Host "`$buildDir=$buildDir"
+Write-Host "`$Env:JAVA_HOME=$Env:JAVA_HOME"
 
 $copyright = "(C) $CopyrightStartYear - $((Get-Date).Year) $Vendor"
 
@@ -71,7 +77,7 @@ if ($clean -and (Test-Path -Path $runtimeImagePath)) {
 ## download jfx jmods for X64, while they are part of the Arm64 JDK
 $archCode = (Get-CimInstance Win32_Processor).Architecture
 $archName = switch ($archCode) {
-    9  { "x64 (AMD64)" }
+    9  { "x64" }
     12 { "ARM64" }
     default { "WMI Win32_Processor.Architecture code ($archCode)" }
 }
@@ -86,14 +92,14 @@ switch ($archName) {
 
         $jmodPaths = "$Env:JAVA_HOME/jmods"
     }
-    'x64 (AMD64)' {
+    'x64' {
 		$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}..."
+			Write-Host "Downloading ${javaFxJmodsUrl}..."
 			Invoke-WebRequest $javaFxJmodsUrl -OutFile $javaFxJmods # redirects are followed by default
 		}
 
@@ -139,6 +145,29 @@ if ($clean -and (Test-Path -Path $appPath)) {
 	Remove-Item -Path $appPath -Force -Recurse
 }
 
+
+$javaOptions = @(
+"--java-options", "--enable-native-access=javafx.graphics,org.cryptomator.jfuse.win,org.cryptomator.integrations.win"
+"--java-options", "-Xss5m"
+"--java-options", "-Xmx256m"
+"--java-options", "-Dcryptomator.appVersion=`"$semVerNo`""
+"--java-options", "-Dfile.encoding=`"utf-8`""
+"--java-options", "-Djava.net.useSystemProxies=true"
+"--java-options", "-Dcryptomator.logDir=`"@{localappdata}/$AppName`""
+"--java-options", "-Dcryptomator.pluginDir=`"@{appdata}/$AppName/Plugins`""
+"--java-options", "-Dcryptomator.settingsPath=`"@{appdata}/$AppName/settings.json;@{userhome}/AppData/Roaming/$AppName/settings.json`""
+"--java-options", "-Dcryptomator.ipcSocketPath=`"@{localappdata}/$AppName/ipc.socket`""
+"--java-options", "-Dcryptomator.p12Path=`"@{appdata}/$AppName/key.p12;@{userhome}/AppData/Roaming/$AppName/key.p12`""
+"--java-options", "-Dcryptomator.mountPointsDir=`"@{userhome}/$AppName`""
+"--java-options", "-Dcryptomator.loopbackAlias=`"$LoopbackAlias`""
+"--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.windowsHelloKeychainPaths=`"@{appdata}/$AppName/windowsHelloKeychain.json`""
+"--java-options", "-Dcryptomator.showTrayIcon=true"
+"--java-options", "-Dcryptomator.buildNumber=`"msi-$revisionNo`""
+)
+
+
 # create app dir
 & "$Env:JAVA_HOME\bin\jpackage" `
 	--verbose `
@@ -151,28 +180,16 @@ if ($clean -and (Test-Path -Path $appPath)) {
 	--name $AppName `
 	--vendor $Vendor `
 	--copyright $copyright `
-	--java-options "--enable-preview" `
-	--java-options "--enable-native-access=javafx.graphics,org.cryptomator.jfuse.win,org.cryptomator.integrations.win" `
-	--java-options "-Xss5m" `
-	--java-options "-Xmx256m" `
-	--java-options "-Dcryptomator.appVersion=`"$semVerNo`"" `
 	--app-version "$semVerNo.$revisionNo" `
-	--java-options "-Dfile.encoding=`"utf-8`"" `
-	--java-options "-Djava.net.useSystemProxies=true" `
-	--java-options "-Dcryptomator.logDir=`"@{localappdata}/$AppName`"" `
-	--java-options "-Dcryptomator.pluginDir=`"@{appdata}/$AppName/Plugins`"" `
-	--java-options "-Dcryptomator.settingsPath=`"@{appdata}/$AppName/settings.json;@{userhome}/AppData/Roaming/$AppName/settings.json`"" `
-	--java-options "-Dcryptomator.ipcSocketPath=`"@{localappdata}/$AppName/ipc.socket`"" `
-	--java-options "-Dcryptomator.p12Path=`"@{appdata}/$AppName/key.p12;@{userhome}/AppData/Roaming/$AppName/key.p12`"" `
-	--java-options "-Dcryptomator.mountPointsDir=`"@{userhome}/$AppName`"" `
-	--java-options "-Dcryptomator.loopbackAlias=`"$LoopbackAlias`"" `
-	--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.windowsHelloKeychainPaths=`"@{appdata}/$AppName/windowsHelloKeychain.json`"" `
-	--java-options "-Dcryptomator.showTrayIcon=true" `
-	--java-options "-Dcryptomator.buildNumber=`"msi-$revisionNo`"" `
 	--resource-dir resources `
-	--icon resources/$AppName.ico
+	--icon resources/$AppName.ico `
+	--add-launcher "${AppName} (Debug)=$buildDir\debug-launcher.properties" `
+	@javaOptions
+
+if ($LASTEXITCODE -ne 0) {
+    Write-Error "jpackage Appimage failed with exit code $LASTEXITCODE"
+	return 1;
+}
 
 #Create RTF license for msi
 &mvn -B -f $buildDir/../../pom.xml license:add-third-party "-Djavafx.platform=win" `
@@ -187,6 +204,7 @@ if ($clean -and (Test-Path -Path $appPath)) {
 # patch app dir
 Copy-Item "contrib\*" -Destination "$AppName"
 attrib -r "$AppName\$AppName.exe"
+attrib -r "$AppName\${AppName} (Debug).exe"
 # patch batch script to set hostfile
 $webDAVPatcher = "$AppName\patchWebDAV.bat"
 try {
@@ -237,7 +255,7 @@ if ($LASTEXITCODE -ne 0) {
 # download Winfsp
 $winfspMsiUrl= 'https://github.com/winfsp/winfsp/releases/download/v2.1/winfsp-2.1.25156.msi'
 $winfspMsiHash = '073A70E00F77423E34BED98B86E600DEF93393BA5822204FAC57A29324DB9F7A'
-Write-Output "Downloading ${winfspMsiUrl}..."
+Write-Host "Downloading ${winfspMsiUrl}..."
 Invoke-WebRequest $winfspMsiUrl -OutFile ".\bundle\resources\winfsp.msi" # redirects are followed by default
 $computedHash = $(Get-FileHash -Path '.\bundle\resources\winfsp.msi' -Algorithm SHA256).Hash
 if (! $computedHash.Equals($winfspMsiHash)) {
@@ -251,7 +269,7 @@ if (! $computedHash.Equals($winfspMsiHash)) {
 
 # download legacy-winfsp uninstaller
 $winfspUninstaller= 'https://github.com/cryptomator/winfsp-uninstaller/releases/latest/download/winfsp-uninstaller.exe'
-Write-Output "Downloading ${winfspUninstaller}..."
+Write-Host "Downloading ${winfspUninstaller}..."
 Invoke-WebRequest $winfspUninstaller -OutFile ".\bundle\resources\winfsp-uninstaller.exe" # redirects are followed by default
 
 # copy MSI to bundle resources
@@ -271,4 +289,18 @@ Copy-Item ".\installer\$AppName-*.msi" -Destination ".\bundle\resources\$AppName
     .\bundle\bundleWithWinfsp.wxs `
     -out "installer\$AppName-Installer.exe"
 
-Write-Output "Created EXE installer .\installer\$AppName-Installer.exe"
+Write-Host "Created EXE installer .\installer\$AppName-Installer.exe"
+return 0;
+}
+
+# ============================
+# Script Execution Starts Here
+# ============================
+if ($clean) {
+	Write-Host "Cleaning up previous build artifacts..."
+	Remove-Item -Path ".\runtime" -Force -Recurse -ErrorAction Ignore
+	Remove-Item -Path ".\$AppName" -Force -Recurse -ErrorAction Ignore
+	Remove-Item -Path ".\installer" -Force -Recurse -ErrorAction Ignore
+}
+return Main
+

+ 4 - 0
dist/win/debug-launcher.properties

@@ -0,0 +1,4 @@
+win-console=true
+win-shortcut=false
+win-menu=false
+description=Debug Launcher with Console for Cryptomator

+ 0 - 15
dist/win/launcher.bat

@@ -1,15 +0,0 @@
-@echo off
-java ^
-	-p "mods" ^
-	-cp "libs/*" ^
-	-Dcryptomator.settingsPath="~/AppData/Roaming/Cryptomator/settings.json" ^
-	-Dcryptomator.ipcSocketPath="~/AppData/Roaming/Cryptomator/ipc.socket" ^
-	-Dcryptomator.logDir="~/AppData/Roaming/Cryptomator" ^
-	-Dcryptomator.mountPointsDir="~/Cryptomator" ^
-	-Dcryptomator.integrationsWin.keychainPaths="~/AppData/Roaming/Cryptomator/keychain.json" ^
-	-Dcryptomator.integrationsWin.windowsHelloKeychainPaths="~/AppData/Roaming/Cryptomator/windowsHelloKeychain.json" ^
-	-Xss20m ^
-	-Xmx512m ^
-	--enable-preview `
-	--enable-native-access=org.cryptomator.jfuse.win `
-	-m org.cryptomator.desktop/org.cryptomator.launcher.Cryptomator

+ 1 - 1
pom.xml

@@ -3,7 +3,7 @@
 	<modelVersion>4.0.0</modelVersion>
 	<groupId>org.cryptomator</groupId>
 	<artifactId>cryptomator</artifactId>
-	<version>1.17.0-SNAPSHOT</version>
+	<version>1.18.0-SNAPSHOT</version>
 	<name>Cryptomator Desktop App</name>
 
 	<organization>

+ 6 - 0
src/main/java/org/cryptomator/common/settings/Settings.java

@@ -25,6 +25,8 @@ import javafx.beans.property.StringProperty;
 import javafx.collections.FXCollections;
 import javafx.collections.ObservableList;
 import javafx.geometry.NodeOrientation;
+
+import java.nio.file.Path;
 import java.time.Instant;
 import java.util.function.Consumer;
 
@@ -75,6 +77,7 @@ public class Settings {
 	public final BooleanProperty checkForUpdates;
 	public final ObjectProperty<Instant> lastUpdateCheckReminder;
 	public final ObjectProperty<Instant> lastSuccessfulUpdateCheck;
+	public final ObjectProperty<Path> previouslyUsedVaultDirectory;
 
 	private Consumer<Settings> saveCmd;
 
@@ -114,6 +117,7 @@ public class Settings {
 		this.checkForUpdates = new SimpleBooleanProperty(this, "checkForUpdates", json.checkForUpdatesEnabled);
 		this.lastUpdateCheckReminder = new SimpleObjectProperty<>(this, "lastUpdateCheckReminder", json.lastReminderForUpdateCheck);
 		this.lastSuccessfulUpdateCheck = new SimpleObjectProperty<>(this, "lastSuccessfulUpdateCheck", json.lastSuccessfulUpdateCheck);
+		this.previouslyUsedVaultDirectory = new SimpleObjectProperty<>(this, "previouslyUsedVaultDirectory", json.previouslyUsedVaultDirectory);
 
 		this.directories.addAll(json.directories.stream().map(VaultSettings::new).toList());
 
@@ -143,6 +147,7 @@ public class Settings {
 		checkForUpdates.addListener(this::somethingChanged);
 		lastUpdateCheckReminder.addListener(this::somethingChanged);
 		lastSuccessfulUpdateCheck.addListener(this::somethingChanged);
+		previouslyUsedVaultDirectory.addListener(this::somethingChanged);
 	}
 
 	@SuppressWarnings("deprecation")
@@ -204,6 +209,7 @@ public class Settings {
 		json.checkForUpdatesEnabled = checkForUpdates.get();
 		json.lastReminderForUpdateCheck = lastUpdateCheckReminder.get();
 		json.lastSuccessfulUpdateCheck = lastSuccessfulUpdateCheck.get();
+		json.previouslyUsedVaultDirectory = previouslyUsedVaultDirectory.get();
 		return json;
 	}
 

+ 4 - 0
src/main/java/org/cryptomator/common/settings/SettingsJson.java

@@ -5,6 +5,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
 import com.fasterxml.jackson.annotation.JsonInclude;
 import com.fasterxml.jackson.annotation.JsonProperty;
 
+import java.nio.file.Path;
 import java.time.Instant;
 import java.util.List;
 
@@ -92,4 +93,7 @@ class SettingsJson {
 
 	@JsonProperty("quickAccessService")
 	String quickAccessService = Settings.DEFAULT_QUICKACCESS_SERVICE;
+
+	@JsonProperty("previouslyUsedVaultDirectory")
+	Path previouslyUsedVaultDirectory;
 }

+ 13 - 13
src/main/java/org/cryptomator/common/vaults/VaultListManager.java

@@ -8,6 +8,18 @@
  *******************************************************************************/
 package org.cryptomator.common.vaults;
 
+import org.apache.commons.lang3.SystemUtils;
+import org.cryptomator.common.recovery.BackupRestorer;
+import org.cryptomator.common.settings.Settings;
+import org.cryptomator.common.settings.VaultSettings;
+import org.cryptomator.cryptofs.CryptoFileSystemProvider;
+import org.cryptomator.cryptofs.DirStructure;
+import org.cryptomator.cryptofs.migration.Migrators;
+import org.cryptomator.integrations.mount.MountService;
+import org.cryptomator.ui.keyloading.masterkeyfile.MasterkeyFileLoadingStrategy;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 import javax.inject.Inject;
 import javax.inject.Singleton;
 import javafx.collections.ObservableList;
@@ -25,18 +37,6 @@ import static org.cryptomator.common.Constants.MASTERKEY_FILENAME;
 import static org.cryptomator.common.Constants.VAULTCONFIG_FILENAME;
 import static org.cryptomator.common.vaults.VaultState.Value.*;
 
-import org.apache.commons.lang3.SystemUtils;
-import org.cryptomator.common.Constants;
-import org.cryptomator.common.recovery.BackupRestorer;
-import org.cryptomator.common.settings.Settings;
-import org.cryptomator.common.settings.VaultSettings;
-import org.cryptomator.cryptofs.CryptoFileSystemProvider;
-import org.cryptomator.cryptofs.DirStructure;
-import org.cryptomator.cryptofs.migration.Migrators;
-import org.cryptomator.integrations.mount.MountService;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
 @Singleton
 public class VaultListManager {
 
@@ -137,7 +137,7 @@ public class VaultListManager {
 					vaultSettings.lastKnownKeyLoader.set(keyIdScheme);
 				}
 			} else if (vaultState == NEEDS_MIGRATION) {
-				vaultSettings.lastKnownKeyLoader.set(Constants.DEFAULT_KEY_ID.toString());
+				vaultSettings.lastKnownKeyLoader.set(MasterkeyFileLoadingStrategy.SCHEME);
 			}
 
 			if (vaultState != VAULT_CONFIG_MISSING) {

+ 8 - 0
src/main/java/org/cryptomator/ipc/Server.java

@@ -53,18 +53,26 @@ class Server implements IpcCommunicator {
 	@Override
 	public void listen(IpcMessageListener listener, Executor executor) {
 		executor.execute(() -> {
+			int errorCount = 0;
 			while (serverSocketChannel.isOpen()) {
 				try (var ch = serverSocketChannel.accept()) {
 					while (ch.isConnected()) {
 						var msg = IpcMessage.receive(ch);
 						listener.handleMessage(msg);
 					}
+					errorCount = 0;
 				} catch (AsynchronousCloseException e) {
+					LOG.info("Closing server socket due to closed channel.");
 					return; // serverSocketChannel closed or listener interrupted
 				} catch (EOFException | ClosedChannelException e) {
 					// continue with next connected client
 				} catch (IOException e) {
+					errorCount++;
 					LOG.error("Failed to read IPC message", e);
+					if(errorCount > 100) { //apparently something is broken, prevent log spam
+						LOG.info("Closing server socket due to too many failed requests.");
+						return;
+					}
 				}
 			}
 		});

+ 3 - 0
src/main/java/org/cryptomator/logging/LogbackConfigurator.java

@@ -90,6 +90,9 @@ public class LogbackConfigurator extends ContextAwareBase implements Configurato
 			// configure fuse file locking logger:
 			Logger fuseLocking = context.getLogger("org.cryptomator.frontend.fuse.locks");
 			fuseLocking.setLevel(Level.OFF);
+			//deactivate kwallet unsettling message
+			Logger kdeWallet = context.getLogger("org.purejava.kwallet.freedesktop.dbus.handlers");
+			kdeWallet.setLevel(Level.OFF);
 		}
 		return ExecutionStatus.DO_NOT_INVOKE_NEXT_IF_ANY;
 	}

+ 1 - 1
src/main/java/org/cryptomator/ui/addvaultwizard/CreateNewVaultExpertSettingsController.java

@@ -26,7 +26,7 @@ public class CreateNewVaultExpertSettingsController implements FxController {
 
 	public static final int MAX_SHORTENING_THRESHOLD = 220;
 	public static final int MIN_SHORTENING_THRESHOLD = 36;
-	private static final String DOCS_NAME_SHORTENING_URL = "https://docs.cryptomator.org/security/architecture/#name-shortening";
+	private static final String DOCS_NAME_SHORTENING_URL = "https://docs.cryptomator.org/security/vault/#name-shortening";
 
 	private final Stage window;
 	private final Lazy<Application> application;

+ 22 - 0
src/main/java/org/cryptomator/ui/addvaultwizard/CreateNewVaultLocationController.java

@@ -4,6 +4,7 @@ import dagger.Lazy;
 import org.cryptomator.common.ObservableUtil;
 import org.cryptomator.common.locationpresets.LocationPreset;
 import org.cryptomator.common.locationpresets.LocationPresetsProvider;
+import org.cryptomator.common.settings.Settings;
 import org.cryptomator.ui.common.FxController;
 import org.cryptomator.ui.common.FxmlFile;
 import org.cryptomator.ui.common.FxmlScene;
@@ -38,6 +39,7 @@ import javafx.stage.WindowEvent;
 import java.io.File;
 import java.io.IOException;
 import java.nio.file.Files;
+import java.nio.file.InvalidPathException;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.Optional;
@@ -64,6 +66,7 @@ public class CreateNewVaultLocationController implements FxController {
 	private final BooleanProperty loadingPresetLocations = new SimpleBooleanProperty(false);
 	private final ObservableList<Node> radioButtons;
 	private final ObservableList<Node> sortedRadioButtons;
+	private final Settings settings;
 
 	private Path customVaultPath = DEFAULT_CUSTOM_VAULT_PATH;
 
@@ -82,6 +85,7 @@ public class CreateNewVaultLocationController implements FxController {
 									 @FxmlScene(FxmlFile.ADDVAULT_NEW_EXPERT_SETTINGS) Lazy<Scene> chooseExpertSettingsScene, //
 									 ObjectProperty<Path> vaultPath, //
 									 @Named("vaultName") StringProperty vaultName, //
+									 Settings settings, //
 									 ExecutorService backgroundExecutor, ResourceBundle resourceBundle) {
 		this.window = window;
 		this.chooseNameScene = chooseNameScene;
@@ -96,6 +100,18 @@ public class CreateNewVaultLocationController implements FxController {
 		this.usePresetPath = new SimpleBooleanProperty();
 		this.radioButtons = FXCollections.observableArrayList();
 		this.sortedRadioButtons = radioButtons.sorted(this::compareLocationPresets);
+		this.settings = settings;
+
+		Path previouslyUsedDirectory = settings.previouslyUsedVaultDirectory.get();
+		if (previouslyUsedDirectory != null) {
+			try {
+				if (Files.exists(previouslyUsedDirectory) && Files.isDirectory(previouslyUsedDirectory) && isActuallyWritable(previouslyUsedDirectory)) {
+					this.customVaultPath = previouslyUsedDirectory;
+				}
+			} catch (InvalidPathException | NullPointerException e) {
+				LOG.warn("Invalid previously used vault directory path: {}", previouslyUsedDirectory, e);
+			}
+		}
 	}
 
 	private VaultPathStatus validatePath(Path p) throws NullPointerException {
@@ -196,6 +212,12 @@ public class CreateNewVaultLocationController implements FxController {
 	@FXML
 	public void next() {
 		if (validVaultPath.getValue()) {
+			if (this.getVaultPath() != null) {
+				Path parentPath = this.getVaultPath().getParent();
+				if (parentPath != null) {
+					this.settings.previouslyUsedVaultDirectory.setValue(parentPath);
+				}
+			}
 			window.setScene(chooseExpertSettingsScene.get());
 		}
 	}

+ 4 - 3
src/main/java/org/cryptomator/ui/keyloading/KeyLoadingStrategy.java

@@ -46,15 +46,16 @@ public interface KeyLoadingStrategy extends MasterkeyLoader {
 	/**
 	 * Determines whether the provided key loader scheme corresponds to a Masterkey File Vault.
 	 * <p>
-	 * This method checks if the {@code keyLoader} parameter matches the known Masterkey File Vault scheme
+	 * This method checks if the {@code keyLoader} parameter starts with the known Masterkey File Vault scheme
 	 * {@link MasterkeyFileLoadingStrategy#SCHEME}.
+	 * This allows identifying not only exact matches but also variants or extended schemes based on the Masterkey scheme.
 	 * </p>
 	 *
 	 * @param keyLoader A string representing the key loader scheme to be checked.
-	 * @return {@code true} if the given key loader scheme represents a Masterkey File Vault; {@code false} otherwise.
+	 * @return {@code true} if the given key loader scheme starts with the Masterkey File Vault scheme; {@code false} otherwise.
 	 */
 	static boolean isMasterkeyFileVault(String keyLoader) {
-		return MasterkeyFileLoadingStrategy.SCHEME.equals(keyLoader);
+		return keyLoader.startsWith(MasterkeyFileLoadingStrategy.SCHEME);
 	}
 
 	/**

+ 1 - 1
src/main/java/org/cryptomator/ui/sharevault/ShareVaultController.java

@@ -19,7 +19,7 @@ public class ShareVaultController implements FxController {
 
 	private static final String SCHEME_PREFIX = "hub+";
 	private static final String VISIT_HUB_URL = "https://cryptomator.org/hub/";
-	private static final String BEST_PRACTICES_URL = "https://docs.cryptomator.org/en/latest/security/best-practices/#sharing-of-vaults";
+	private static final String BEST_PRACTICES_URL = "https://docs.cryptomator.org/security/best-practices/#sharing-of-vaults";
 
 	private final Stage window;
 	private final Lazy<Application> application;

+ 41 - 5
src/main/resources/i18n/strings_ar.properties

@@ -62,9 +62,9 @@ addvaultwizard.new.locationIsOk=الموقع المناسب للمخزن الخ
 addvaultwizard.new.invalidName=اسم المخزن غير صالح
 addvaultwizard.new.validName=اسم المخزن صالح
 addvaultwizard.new.validCharacters.message=قد يحتوي اسم المخزن على الأحرف التالية:
-addvaultwizard.new.validCharacters.chars=أحرف الكلمات (أمثلة: a, ж, 수)
-addvaultwizard.new.validCharacters.numbers=الأعداد
-addvaultwizard.new.validCharacters.dashes=الشرطة (%s) أو الشرطة السفلية (%s)
+addvaultwizard.new.validCharacters.chars=أحرف لكن دون علامات (#, $, !, @...)
+addvaultwizard.new.validCharacters.numbers=الأرقام
+addvaultwizard.new.validCharacters.dashes=ناقص (%s) أو شِرْطَةٌ سفلية (%s)
 ### Expert Settings
 addvaultwizard.new.expertSettings.enableExpertSettingsCheckbox=تمكين إعدادات الخبراء
 addvaultwizard.new.expertSettings.shorteningThreshold.invalid=أدخل قيمة بين 36 و 220 (الافتراضي 220)
@@ -319,7 +319,7 @@ preferences.volume.feature.readOnly=تحميل للقراءة فقط
 ## Updates
 preferences.updates=تحديثات
 preferences.updates.currentVersion=الإصدار الحالي: %s
-preferences.updates.autoUpdateCheck=تحقق من التحديثات اوتوماتيكيا
+preferences.updates.autoUpdateCheck=التحقق من وجود تحديثات تلقائياً
 preferences.updates.checkNowBtn=تحقق الان
 preferences.updates.updateAvailable=التحديث إلى الإصدار %s متاح.
 preferences.updates.lastUpdateCheck=آخر فحص: %s
@@ -395,6 +395,7 @@ main.vaultlist.contextMenu.vaultoptions=إظهار خيارات المخزن
 main.vaultlist.contextMenu.reveal=اظهار القرص
 main.vaultlist.addVaultBtn.menuItemNew=إنشاء مخزن جديد...
 main.vaultlist.addVaultBtn.menuItemExisting=افتح مخزن موجود...
+main.vaultlist.showEventsButton.tooltip=عرض الإشعارات
 ##Notificaition
 main.notification.updateAvailable=هناك تحديث متاح.
 main.notification.support=دعم Cryptomator.
@@ -423,7 +424,9 @@ main.vaultDetail.stats=إحصائيات الخزنة
 main.vaultDetail.locateEncryptedFileBtn=تحديد موقع الملف المشفر
 main.vaultDetail.locateEncryptedFileBtn.tooltip=اختر ملف من خزانتك لتحديد مكان نظيره المشفر
 main.vaultDetail.encryptedPathsCopied=تم نسخ مسارات الملفات إلى الحافظة!
+main.vaultDetail.locateEncrypted.filePickerTitle=اختر الملَف من الخزنة
 main.vaultDetail.decryptName.buttonLabel=فك تشفير اسم الملف
+main.vaultDetail.decryptName.tooltip=اختر ملَف مشفر لفك تشفير اسمه
 ### Missing
 main.vaultDetail.missing.info=لم يتمكن Cryptomator من العثور على خزنة في هذا المسار.
 main.vaultDetail.missing.recheck=إعادة الفحص
@@ -473,7 +476,7 @@ vaultOptions.mount.mountPoint.custom=استخدام المجلد المختار
 vaultOptions.mount.mountPoint.directoryPickerButton=اختر…
 vaultOptions.mount.mountPoint.directoryPickerTitle=إختر مجلد
 vaultOptions.mount.volumeType.default=الافتراضي (%s)
-vaultOptions.mount.volumeType.restartRequired=لاستخدام هذا النوع من وحدة التخزين يحتاج Cryptomator إلى إعادة تشغيله.
+vaultOptions.mount.volumeType.restartRequired=لاستخدام هذا النوع من وحدة التخزين يحتاج Cryptomator إلى إعادة تشغيل.
 vaultOptions.mount.volume.tcp.port=منفذ TCP
 vaultOptions.mount.volume.type=‮نوع وحدة التخزين
 ## Master Key
@@ -580,7 +583,40 @@ shareVault.hub.instruction.2=2. امنح الوصول لعضو الفريق في
 shareVault.hub.openHub=زيارة Cryptomator Hub
 
 # Decrypt File Names
+decryptNames.title=فك تشفير اسم الملَف
+decryptNames.filePicker.title=اختر ملَف مشفر
+decryptNames.filePicker.extensionDescription=ملف مشفر
+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
+eventView.title=أحداث
+eventView.filter.allVaults=الكل
+eventView.clearListButton.tooltip=تفريغ القائمة
 ## event list entries
+eventView.entry.vaultLocked.description=فتح "%s" للحصول على التفاصيل
+eventView.entry.conflictResolved.message=تم حل التضارب
+eventView.entry.conflictResolved.showDecrypted=إظهار الملف غير المشفر
+eventView.entry.conflictResolved.copyDecrypted=نسخ المسار غير المشفر
+eventView.entry.conflict.message=فشل حل التضارب
+eventView.entry.conflict.showDecrypted=إظهار الملَف غير المشفر الأصلي
+eventView.entry.conflict.copyDecrypted=نسخ المسار غير المشفر والأصلي
+eventView.entry.conflict.showEncrypted=إظهار ملف متضارب ومشفر
+eventView.entry.conflict.copyEncrypted=نسخ مسار التشفير المتعارض
+eventView.entry.decryptionFailed.message=فشل فك التشفير
+eventView.entry.decryptionFailed.showEncrypted=عرض ملَف المشفر
+eventView.entry.decryptionFailed.copyEncrypted=نسخ مسار المشفر
+eventView.entry.brokenDirFile.message=رابط الدليل المكسور
+eventView.entry.brokenDirFile.showEncrypted=إظهار الرابط المكسور، المشفر
+eventView.entry.brokenDirFile.copyEncrypted=نسخ مسار الرابط المكسور
+eventView.entry.brokenFileNode.message=عقدة ملفات النظام التافلة
+eventView.entry.brokenFileNode.showEncrypted=عرض العقدة المشفّرة التافلة
+eventView.entry.brokenFileNode.copyEncrypted=نسخ مسار العقدة المشفّرة التافلة
+eventView.entry.brokenFileNode.copyDecrypted=نسخ المسار غير المشفر

+ 24 - 24
src/main/resources/i18n/strings_pt.properties

@@ -424,9 +424,9 @@ main.vaultDetail.stats=Estatísticas do Cofre
 main.vaultDetail.locateEncryptedFileBtn=Localizar Ficheiro Encriptado
 main.vaultDetail.locateEncryptedFileBtn.tooltip=Escolha um ficheiro do seu cofre para localizar a sua contraparte encriptada
 main.vaultDetail.encryptedPathsCopied=Caminhos copiados para a área de transferência!
-main.vaultDetail.locateEncrypted.filePickerTitle=Selecionar ficheiro dentro do cofre
-main.vaultDetail.decryptName.buttonLabel=Desencriptar nome do ficheiro
-main.vaultDetail.decryptName.tooltip=Escolha um ficheiro de cofre encriptado para desencriptar o seu nome
+main.vaultDetail.locateEncrypted.filePickerTitle=Selecione o ficheiro no cofre
+main.vaultDetail.decryptName.buttonLabel=Descriptografar o nome do ficheiro
+main.vaultDetail.decryptName.tooltip=Escolha um ficheiro encriptado do cofre para desencriptar o seu nome
 ### Missing
 main.vaultDetail.missing.info=O Cryptomator não conseguiu encontrar um cofre neste diretório.
 main.vaultDetail.missing.recheck=Verificar novamente
@@ -583,17 +583,17 @@ shareVault.hub.instruction.2=2. Conceder acesso ao membro da equipe no Hub Crypt
 shareVault.hub.openHub=Abrir Hub do Cryptomator
 
 # Decrypt File Names
-decryptNames.title=Desencriptar nomes de ficheiros
+decryptNames.title=Desencriptar os nomes dos ficheiros
 decryptNames.filePicker.title=Selecione o ficheiro encriptado
-decryptNames.filePicker.extensionDescription=Ficheiro encriptado do Cryptomator
-decryptNames.copyTable.tooltip=Copiar tabela
-decryptNames.clearTable.tooltip=Limpar tabela
-decryptNames.copyHint=Copiar conteúdo da célula com %s
-decryptNames.dropZone.message=Solte os ficheiros ou clique para selecionar
-decryptNames.dropZone.error.vaultInternalFiles=Ficheiros internos do cofre sem nome decifrável selecionado
-decryptNames.dropZone.error.foreignFiles=Ficheiros não pertencem ao cofre "%s"
+decryptNames.filePicker.extensionDescription=Ficheiro encriptado pelo Criptomator
+decryptNames.copyTable.tooltip=Copiar a tabela
+decryptNames.clearTable.tooltip=Limpar a tabela
+decryptNames.copyHint=Copiar o conteúdo da célula com %s
+decryptNames.dropZone.message=Largue os ficheiros ou clique para selecionar
+decryptNames.dropZone.error.vaultInternalFiles=Ficheiros internos do coftre sem nome desencriptável selecionado
+decryptNames.dropZone.error.foreignFiles=Os ficheiros não pertencem ao cofre "%s"
 decryptNames.dropZone.error.noDirIdBackup=O diretório dos ficheiros selecionados não contém o ficheiro dirId.c9r
-decryptNames.dropZone.error.generic=Falha ao desencriptar nomes de ficheiros
+decryptNames.dropZone.error.generic=Falha ao desencriptar os nomes dos ficheiros
 
 
 # Event View
@@ -603,20 +603,20 @@ eventView.clearListButton.tooltip=Limpar lista
 ## event list entries
 eventView.entry.vaultLocked.description=Desbloquear "%s" para detalhes
 eventView.entry.conflictResolved.message=Conflito resolvido
-eventView.entry.conflictResolved.showDecrypted=Mostrar ficheiro desencriptado
-eventView.entry.conflictResolved.copyDecrypted=Copiar caminho desencriptado
-eventView.entry.conflict.message=Resolução de conflito falhou
-eventView.entry.conflict.showDecrypted=Mostrar ficheiro original desencriptado
-eventView.entry.conflict.copyDecrypted=Copie caminho original desencriptado
-eventView.entry.conflict.showEncrypted=Mostrar ficheiro encriptado conflitante
-eventView.entry.conflict.copyEncrypted=Copiar caminho encriptado conflituante
-eventView.entry.decryptionFailed.message=Falha na desencriptação
+eventView.entry.conflictResolved.showDecrypted=Mostrar o ficheiro desencriptado
+eventView.entry.conflictResolved.copyDecrypted=Copiar o caminho desencriptado
+eventView.entry.conflict.message=A resolução do conflito falhou
+eventView.entry.conflict.showDecrypted=Mostrar o ficheiro original desencriptado
+eventView.entry.conflict.copyDecrypted=Copie o caminho original desencriptado
+eventView.entry.conflict.showEncrypted=Mostrar o ficheiro encriptado em conflito
+eventView.entry.conflict.copyEncrypted=Copiar o caminho encriptado em conflito
+eventView.entry.decryptionFailed.message=A desencriptação falhou
 eventView.entry.decryptionFailed.showEncrypted=Mostrar ficheiro encriptado
-eventView.entry.decryptionFailed.copyEncrypted=Copiar caminho de encriptação
+eventView.entry.decryptionFailed.copyEncrypted=Copiar o caminho encriptado
 eventView.entry.brokenDirFile.message=Link de diretório quebrado
-eventView.entry.brokenDirFile.showEncrypted=Mostrar link quebrado e encriptado
+eventView.entry.brokenDirFile.showEncrypted=Mostrar o link quebrado e encriptado
 eventView.entry.brokenDirFile.copyEncrypted=Copiar caminho do link quebrado
 eventView.entry.brokenFileNode.message=Nó do sistema de ficheiros avariado
-eventView.entry.brokenFileNode.showEncrypted=Mostrar nó encriptado quebrado
+eventView.entry.brokenFileNode.showEncrypted=Mostrar nó encriptado e danificado
 eventView.entry.brokenFileNode.copyEncrypted=Copiar o caminho do nó encriptado e danificado
-eventView.entry.brokenFileNode.copyDecrypted=Copiar caminho desencriptado
+eventView.entry.brokenFileNode.copyDecrypted=Copiar o caminho desencriptado