mirror of
https://github.com/cryptomator/cryptomator.git
synced 2026-09-24 08:54:42 +00:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
93fe27989a | ||
|
|
a8344e5640 |
@@ -48,7 +48,7 @@ runs:
|
|||||||
echo "client-secret=${{ inputs.client-secret }}" >> "$GITHUB_OUTPUT"
|
echo "client-secret=${{ inputs.client-secret }}" >> "$GITHUB_OUTPUT"
|
||||||
shell: bash
|
shell: bash
|
||||||
- name: Sign DLLs with Azure Trusted Signing
|
- name: Sign DLLs with Azure Trusted Signing
|
||||||
uses: azure/artifact-signing-action@87c2e83e6868da99d3380aa309851b32ed9a8346 # v1.1.0
|
uses: azure/trusted-signing-action@fc390cf8ed0f14e248a542af1d838388a47c7a7c # v0.5.10
|
||||||
with:
|
with:
|
||||||
files-folder: ${{ inputs.base-dir }}
|
files-folder: ${{ inputs.base-dir }}
|
||||||
files-folder-filter: ${{ inputs.file-extensions }}
|
files-folder-filter: ${{ inputs.file-extensions }}
|
||||||
@@ -59,7 +59,7 @@ runs:
|
|||||||
azure-tenant-id: ${{ steps.set-secrets.outputs.tenant-id }}
|
azure-tenant-id: ${{ steps.set-secrets.outputs.tenant-id }}
|
||||||
azure-client-id: ${{ steps.set-secrets.outputs.client-id }}
|
azure-client-id: ${{ steps.set-secrets.outputs.client-id }}
|
||||||
azure-client-secret: ${{ steps.set-secrets.outputs.client-secret }}
|
azure-client-secret: ${{ steps.set-secrets.outputs.client-secret }}
|
||||||
signing-account-name: cryptomatorSigning
|
trusted-signing-account-name: cryptomatorSigning
|
||||||
certificate-profile-name: production
|
certificate-profile-name: production
|
||||||
endpoint: https://weu.codesigning.azure.net/
|
endpoint: https://weu.codesigning.azure.net/
|
||||||
timestamp-rfc3161: http://timestamp.acs.microsoft.com
|
timestamp-rfc3161: http://timestamp.acs.microsoft.com
|
||||||
|
|||||||
@@ -14,9 +14,6 @@ updates:
|
|||||||
versions: ["2.0.1.MR"]
|
versions: ["2.0.1.MR"]
|
||||||
- dependency-name: "org.openjfx:*"
|
- dependency-name: "org.openjfx:*"
|
||||||
update-types: ["version-update:semver-major"]
|
update-types: ["version-update:semver-major"]
|
||||||
# due to https://github.com/fabriciorby/maven-surefire-junit5-tree-reporter/issues/68
|
|
||||||
- dependency-name: "org.apache.maven.plugins:maven-surefire-plugin"
|
|
||||||
versions: [ "3.5.4", "3.5.5" ]
|
|
||||||
groups:
|
groups:
|
||||||
java-test-dependencies:
|
java-test-dependencies:
|
||||||
patterns:
|
patterns:
|
||||||
|
|||||||
@@ -8,10 +8,6 @@ on:
|
|||||||
version:
|
version:
|
||||||
description: 'Version'
|
description: 'Version'
|
||||||
required: false
|
required: false
|
||||||
create-pr:
|
|
||||||
description: 'Create a PR for aur-bin repo'
|
|
||||||
type: boolean
|
|
||||||
default: false
|
|
||||||
push:
|
push:
|
||||||
branches-ignore:
|
branches-ignore:
|
||||||
- 'dependabot/**'
|
- 'dependabot/**'
|
||||||
@@ -23,7 +19,7 @@ on:
|
|||||||
|
|
||||||
env:
|
env:
|
||||||
JAVA_DIST: 'temurin'
|
JAVA_DIST: 'temurin'
|
||||||
JAVA_VERSION: '25.0.2+10.0.LTS'
|
JAVA_VERSION: '25.0.1+8.0.LTS'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
get-version:
|
get-version:
|
||||||
@@ -35,26 +31,22 @@ jobs:
|
|||||||
name: Build AppImage
|
name: Build AppImage
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
needs: [get-version]
|
needs: [get-version]
|
||||||
env:
|
|
||||||
SEMVER_STR: ${{ needs.get-version.outputs.semVerStr }}
|
|
||||||
SEMVER_NUM: ${{ needs.get-version.outputs.semVerNum }}
|
|
||||||
REV_NUM: ${{ needs.get-version.outputs.revNum }}
|
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- os: ubuntu-latest
|
- os: ubuntu-latest
|
||||||
arch: x86_64
|
appimage-suffix: x86_64
|
||||||
openjfx-url: 'https://download2.gluonhq.com/openjfx/25.0.2/openjfx-25.0.2_linux-x64_bin-jmods.zip'
|
openjfx-url: 'https://download2.gluonhq.com/openjfx/25/openjfx-25_linux-x64_bin-jmods.zip'
|
||||||
openjfx-sha: 'e0a9c29d8cf3af9b8b48848b43f87b5785bc107c53a951b19668ce05842bba1b'
|
openjfx-sha: '96e520f48610d8ffb94ca30face1f11ffe8a977ddc1c4ff80b1a9e9f048bd94e'
|
||||||
- os: ubuntu-24.04-arm
|
- os: ubuntu-24.04-arm
|
||||||
arch: aarch64
|
appimage-suffix: aarch64
|
||||||
openjfx-url: 'https://download2.gluonhq.com/openjfx/25.0.2/openjfx-25.0.2_linux-aarch64_bin-jmods.zip'
|
openjfx-url: 'https://download2.gluonhq.com/openjfx/25/openjfx-25_linux-aarch64_bin-jmods.zip'
|
||||||
openjfx-sha: 'c3408f818693cce09e59829a8e862a82c7695fdfcd585c41cfd527f5fc3fe646'
|
openjfx-sha: '9ad4ca7b769ca4ee6419f1e99143dd6ff812f8be4fddb46a7d7cacbeea148af4'
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||||
- name: Setup Java
|
- name: Setup Java
|
||||||
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
|
uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # v5.1.0
|
||||||
with:
|
with:
|
||||||
distribution: ${{ env.JAVA_DIST }}
|
distribution: ${{ env.JAVA_DIST }}
|
||||||
java-version: ${{ env.JAVA_VERSION }}
|
java-version: ${{ env.JAVA_VERSION }}
|
||||||
@@ -63,7 +55,7 @@ jobs:
|
|||||||
- name: Download OpenJFX jmods
|
- name: Download OpenJFX jmods
|
||||||
id: download-jmods
|
id: download-jmods
|
||||||
run: |
|
run: |
|
||||||
curl --silent --fail-with-body --proto "=https" -L ${{ matrix.openjfx-url }} -o openjfx-jmods.zip
|
curl -L ${{ matrix.openjfx-url }} -o openjfx-jmods.zip
|
||||||
echo "${{ matrix.openjfx-sha }} openjfx-jmods.zip" | shasum -a256 --check
|
echo "${{ matrix.openjfx-sha }} openjfx-jmods.zip" | shasum -a256 --check
|
||||||
mkdir -p openjfx-jmods
|
mkdir -p openjfx-jmods
|
||||||
unzip -j openjfx-jmods.zip \*/javafx.base.jmod \*/javafx.controls.jmod \*/javafx.fxml.jmod \*/javafx.graphics.jmod -d openjfx-jmods
|
unzip -j openjfx-jmods.zip \*/javafx.base.jmod \*/javafx.controls.jmod \*/javafx.fxml.jmod \*/javafx.graphics.jmod -d openjfx-jmods
|
||||||
@@ -81,7 +73,7 @@ jobs:
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
- name: Set version
|
- name: Set version
|
||||||
run : mvn versions:set -DnewVersion="$SEMVER_STR"
|
run : mvn versions:set -DnewVersion=${{ needs.get-version.outputs.semVerStr }}
|
||||||
- name: Run maven
|
- name: Run maven
|
||||||
run: mvn -B clean package -Plinux -DskipTests
|
run: mvn -B clean package -Plinux -DskipTests
|
||||||
- name: Patch target dir
|
- name: Patch target dir
|
||||||
@@ -102,15 +94,13 @@ jobs:
|
|||||||
${JAVA_HOME}/bin/jlink
|
${JAVA_HOME}/bin/jlink
|
||||||
--verbose
|
--verbose
|
||||||
--output runtime
|
--output runtime
|
||||||
--module-path "${JMOD_PATHS}"
|
--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.cryptoki,jdk.crypto.ec,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.crypto.cryptoki,jdk.crypto.ec,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
|
||||||
--no-man-pages
|
--no-man-pages
|
||||||
--strip-debug
|
--strip-debug
|
||||||
--compress zip-0
|
--compress zip-0
|
||||||
env:
|
|
||||||
JMOD_PATHS: ${{ steps.jep-493-check.outputs.jmod_paths }}
|
|
||||||
- name: Run jpackage
|
- name: Run jpackage
|
||||||
run: >
|
run: >
|
||||||
${JAVA_HOME}/bin/jpackage
|
${JAVA_HOME}/bin/jpackage
|
||||||
@@ -124,23 +114,23 @@ jobs:
|
|||||||
--name Cryptomator
|
--name Cryptomator
|
||||||
--vendor "Skymatic GmbH"
|
--vendor "Skymatic GmbH"
|
||||||
--copyright "(C) 2016 - 2025 Skymatic GmbH"
|
--copyright "(C) 2016 - 2025 Skymatic GmbH"
|
||||||
--app-version "${SEMVER_NUM}.${REV_NUM}"
|
--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=javafx.graphics,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=\"${SEMVER_STR}\""
|
--java-options "-Dcryptomator.appVersion=\"${{ needs.get-version.outputs.semVerStr }}\""
|
||||||
--java-options "-Dfile.encoding=\"utf-8\""
|
--java-options "-Dfile.encoding=\"utf-8\""
|
||||||
--java-options "-Djava.net.useSystemProxies=true"
|
--java-options "-Djava.net.useSystemProxies=true"
|
||||||
--java-options "-Dcryptomator.adminConfigPath=\"/etc/cryptomator/config.properties\""
|
|
||||||
--java-options "-Dcryptomator.logDir=\"@{userhome}/.local/share/Cryptomator/logs\""
|
--java-options "-Dcryptomator.logDir=\"@{userhome}/.local/share/Cryptomator/logs\""
|
||||||
|
--java-options "-Dcryptomator.pluginDir=\"@{userhome}/.local/share/Cryptomator/plugins\""
|
||||||
--java-options "-Dcryptomator.settingsPath=\"@{userhome}/.config/Cryptomator/settings.json:@{userhome}/.Cryptomator/settings.json\""
|
--java-options "-Dcryptomator.settingsPath=\"@{userhome}/.config/Cryptomator/settings.json:@{userhome}/.Cryptomator/settings.json\""
|
||||||
--java-options "-Dcryptomator.p12Path=\"@{userhome}/.config/Cryptomator/key.p12\""
|
--java-options "-Dcryptomator.p12Path=\"@{userhome}/.config/Cryptomator/key.p12\""
|
||||||
--java-options "-Dcryptomator.ipcSocketPath=\"@{userhome}/.config/Cryptomator/ipc.socket\""
|
--java-options "-Dcryptomator.ipcSocketPath=\"@{userhome}/.config/Cryptomator/ipc.socket\""
|
||||||
--java-options "-Dcryptomator.mountPointsDir=\"@{userhome}/.local/share/Cryptomator/mnt\""
|
--java-options "-Dcryptomator.mountPointsDir=\"@{userhome}/.local/share/Cryptomator/mnt\""
|
||||||
--java-options "-Dcryptomator.showTrayIcon=true"
|
--java-options "-Dcryptomator.showTrayIcon=true"
|
||||||
--java-options "-Dcryptomator.integrationsLinux.trayIconsDir=\"@{appdir}/usr/share/icons/hicolor/symbolic/apps\""
|
--java-options "-Dcryptomator.integrationsLinux.trayIconsDir=\"@{appdir}/usr/share/icons/hicolor/symbolic/apps\""
|
||||||
--java-options "-Dcryptomator.buildNumber=\"appimage-${REV_NUM}\""
|
--java-options "-Dcryptomator.buildNumber=\"appimage-${{ needs.get-version.outputs.revNum }}\""
|
||||||
--java-options "-Dcryptomator.networking.truststore.p12Path=\"/etc/cryptomator/certs.p12\""
|
--java-options "-Dcryptomator.networking.truststore.p12Path=\"/etc/cryptomator/certs.p12\""
|
||||||
--java-options "-XX:ErrorFile=/cryptomator/cryptomator_crash.log"
|
--java-options "-XX:ErrorFile=/cryptomator/cryptomator_crash.log"
|
||||||
--resource-dir dist/linux/resources
|
--resource-dir dist/linux/resources
|
||||||
@@ -165,7 +155,7 @@ jobs:
|
|||||||
ln -s bin/cryptomator.sh Cryptomator.AppDir/AppRun
|
ln -s bin/cryptomator.sh Cryptomator.AppDir/AppRun
|
||||||
- name: Download AppImageKit
|
- name: Download AppImageKit
|
||||||
run: |
|
run: |
|
||||||
curl --silent --fail-with-body --proto "=https" -L "https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-${{ matrix.arch }}.AppImage" -o appimagetool.AppImage
|
curl -L https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-${{ matrix.appimage-suffix }}.AppImage -o appimagetool.AppImage
|
||||||
chmod +x appimagetool.AppImage
|
chmod +x appimagetool.AppImage
|
||||||
./appimagetool.AppImage --appimage-extract
|
./appimagetool.AppImage --appimage-extract
|
||||||
- name: Prepare GPG-Agent for signing with key 615D449FE6E6A235
|
- name: Prepare GPG-Agent for signing with key 615D449FE6E6A235
|
||||||
@@ -177,17 +167,17 @@ jobs:
|
|||||||
GPG_PASSPHRASE: ${{ secrets.RELEASES_GPG_PASSPHRASE }}
|
GPG_PASSPHRASE: ${{ secrets.RELEASES_GPG_PASSPHRASE }}
|
||||||
- name: Build AppImage
|
- name: Build AppImage
|
||||||
run: >
|
run: >
|
||||||
./squashfs-root/AppRun Cryptomator.AppDir cryptomator-${SEMVER_STR}-${{ matrix.arch }}.AppImage
|
./squashfs-root/AppRun Cryptomator.AppDir cryptomator-${{ needs.get-version.outputs.semVerStr }}-${{ matrix.appimage-suffix }}.AppImage
|
||||||
-u "gh-releases-zsync|cryptomator|cryptomator|latest|cryptomator-*-${{ matrix.arch }}.AppImage.zsync"
|
-u "gh-releases-zsync|cryptomator|cryptomator|latest|cryptomator-*-${{ matrix.appimage-suffix }}.AppImage.zsync"
|
||||||
--sign --sign-key=615D449FE6E6A235
|
--sign --sign-key=615D449FE6E6A235
|
||||||
- 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-*.AppImage
|
gpg --batch --quiet --passphrase-fd 0 --pinentry-mode loopback -u 615D449FE6E6A235 --detach-sign -a cryptomator-*.AppImage
|
||||||
gpg --batch --quiet --passphrase-fd 0 --pinentry-mode loopback -u 615D449FE6E6A235 --detach-sign -a cryptomator-*.AppImage.zsync
|
gpg --batch --quiet --passphrase-fd 0 --pinentry-mode loopback -u 615D449FE6E6A235 --detach-sign -a cryptomator-*.AppImage.zsync
|
||||||
- name: Upload artifacts
|
- name: Upload artifacts
|
||||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
|
||||||
with:
|
with:
|
||||||
name: appimage-${{ matrix.arch }}
|
name: appimage-${{ matrix.appimage-suffix }}
|
||||||
path: |
|
path: |
|
||||||
cryptomator-*.AppImage
|
cryptomator-*.AppImage
|
||||||
cryptomator-*.AppImage.zsync
|
cryptomator-*.AppImage.zsync
|
||||||
@@ -206,77 +196,65 @@ jobs:
|
|||||||
|
|
||||||
create-aur-bin-pr:
|
create-aur-bin-pr:
|
||||||
name: Create PR for aur-bin repo
|
name: Create PR for aur-bin repo
|
||||||
if: github.event_name == 'workflow_dispatch' && inputs.create-pr || github.event_name == 'release' && needs.get-version.outputs.versionType == 'stable'
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: [build, get-version]
|
needs: [build, get-version]
|
||||||
container:
|
runs-on: ubuntu-latest
|
||||||
image: archlinux:base-devel
|
if: github.event_name == 'release' && needs.get-version.outputs.versionType == 'stable'
|
||||||
env:
|
|
||||||
SEMVER_STR: ${{ needs.get-version.outputs.semVerStr }}
|
|
||||||
PKGDEST: ${{ github.workspace }}/pkgdest
|
|
||||||
SRCDEST: ${{ github.workspace }}/srcdest
|
|
||||||
steps:
|
steps:
|
||||||
- name: Prepare pacman
|
- name: Download AppImages
|
||||||
|
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
|
||||||
|
with:
|
||||||
|
path: downloads/
|
||||||
|
merge-multiple: true
|
||||||
|
- name: Compute sha256 hash of AppImages
|
||||||
|
id: checksums
|
||||||
run: |
|
run: |
|
||||||
pacman-key --init
|
X64_SHA256=$(sha256sum downloads/cryptomator-*-x86_64.AppImage | cut -d ' ' -f1)
|
||||||
pacman-key --populate archlinux
|
echo "x64-sha256sum=${X64_SHA256}" >> "$GITHUB_OUTPUT"
|
||||||
pacman -Syu --noconfirm --needed git base-devel sudo gnupg maven unzip github-cli curl pacman-contrib
|
AARCH64_SHA256=$(sha256sum downloads/cryptomator-*-aarch64.AppImage | cut -d ' ' -f1)
|
||||||
- name: Checkout cryptomator/aur-bin
|
echo "aarch64-sha256sum=${AARCH64_SHA256}" >> "$GITHUB_OUTPUT"
|
||||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||||
with:
|
with:
|
||||||
repository: 'cryptomator/aur-bin'
|
repository: 'cryptomator/aur-bin'
|
||||||
token: ${{ secrets.CRYPTOBOT_PR_TOKEN }}
|
token: ${{ secrets.CRYPTOBOT_PR_TOKEN }}
|
||||||
- name: Create build user
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
useradd -m builder
|
sudo apt-get update
|
||||||
echo 'builder ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers.d/builder
|
sudo apt-get -y install makepkg pacman-package-manager
|
||||||
chown -R builder:builder "$GITHUB_WORKSPACE"
|
|
||||||
install -d -m 0755 -o builder -g builder "$PKGDEST" "$SRCDEST"
|
|
||||||
- name: Import Cryptomator release signing key
|
|
||||||
# try first ubuntu. on failure try openpgp keyservers
|
|
||||||
run: >
|
|
||||||
sudo -u builder gpg --batch --keyserver hkps://keyserver.ubuntu.com --recv-keys 58117AFA1F85B3EEC154677D615D449FE6E6A235
|
|
||||||
|| sudo -u builder gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys 58117AFA1F85B3EEC154677D615D449FE6E6A235
|
|
||||||
- name: Checkout release branch
|
- name: Checkout release branch
|
||||||
run: |
|
run: |
|
||||||
git config --global safe.directory '*'
|
git checkout -b release/${{ needs.get-version.outputs.semVerStr }}
|
||||||
git checkout -b "release/${SEMVER_STR}"
|
|
||||||
- name: Update build file
|
- name: Update build file
|
||||||
run: |
|
run: |
|
||||||
sed -i -e "s|^pkgver=.*$|pkgver=${SEMVER_STR}|" PKGBUILD
|
sed -i -e 's|^pkgver=.*$|pkgver=${{ needs.get-version.outputs.semVerStr }}|' PKGBUILD
|
||||||
sed -i -e 's|^pkgrel=.*$|pkgrel=1|' PKGBUILD
|
sed -i -e 's|^pkgrel=.*$|pkgrel=1|' PKGBUILD
|
||||||
sudo -u builder updpkgsums
|
sed -i -e "s|^sha256sums_x86_64=.*$|sha256sums_x86_64=('${{ steps.checksums.outputs.x64-sha256sum }}'|" PKGBUILD
|
||||||
sudo -u builder makepkg --printsrcinfo > .SRCINFO
|
sed -i -e "s|^sha256sums_aarch64=.*$|sha256sums_aarch64=('${{ steps.checksums.outputs.aarch64-sha256sum}}'|" PKGBUILD
|
||||||
- name: Build package with makepkg
|
makepkg --printsrcinfo > .SRCINFO
|
||||||
run: >
|
|
||||||
sudo -u builder
|
|
||||||
env PKGDEST="$PKGDEST" SRCDEST="$SRCDEST"
|
|
||||||
makepkg --syncdeps --cleanbuild --noconfirm --log
|
|
||||||
- name: Commit and push
|
- name: Commit and push
|
||||||
run: |
|
run: |
|
||||||
git config user.name "cryptobot"
|
git config user.name "${{ github.actor }}"
|
||||||
git config user.email "cryptobot@users.noreply.github.com"
|
git config user.email "${{ github.actor_id }}+${{ github.actor }}@users.noreply.github.com"
|
||||||
git config push.autoSetupRemote true
|
git config push.autoSetupRemote true
|
||||||
git stage PKGBUILD .SRCINFO
|
git stage .
|
||||||
git commit -m "Prepare release ${SEMVER_STR}"
|
git commit -m "Prepare release ${{needs.get-version.outputs.semVerStr}}"
|
||||||
git push
|
git push
|
||||||
- name: Create pull request
|
- name: Create pull request
|
||||||
id: create-pr
|
id: create-pr
|
||||||
run: |
|
run: |
|
||||||
printf "Created by $GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID" > pr_body.md
|
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 ${SEMVER_STR}" --body-file pr_body.md)
|
URL=$(gh pr create --title "Release ${{ needs.get-version.outputs.semVerStr }}" --body-file pr_body.md)
|
||||||
echo "url=$PR_URL" >> "$GITHUB_OUTPUT"
|
echo "PR_URL=$URL" >> "$GITHUB_OUTPUT"
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ secrets.CRYPTOBOT_PR_TOKEN }}
|
GH_TOKEN: ${{ secrets.CRYPTOBOT_PR_TOKEN }}
|
||||||
- name: Slack Notification
|
- name: Slack Notification
|
||||||
uses: rtCamp/action-slack-notify@e31e87e03dd19038e411e38ae27cbad084a90661 # v2.3.3
|
uses: rtCamp/action-slack-notify@e31e87e03dd19038e411e38ae27cbad084a90661 # v2.3.3
|
||||||
env:
|
env:
|
||||||
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_CRYPTOMATOR_DESKTOP }}
|
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }}
|
||||||
SLACK_USERNAME: 'Cryptobot'
|
SLACK_USERNAME: 'Cryptobot'
|
||||||
SLACK_ICON: false
|
SLACK_ICON: false
|
||||||
SLACK_ICON_EMOJI: ':bot:'
|
SLACK_ICON_EMOJI: ':bot:'
|
||||||
SLACK_CHANNEL: 'cryptomator-desktop'
|
SLACK_CHANNEL: 'cryptomator-desktop'
|
||||||
SLACK_TITLE: "AUR-bin release PR for ${{ github.event.repository.name }} ${{ needs.get-version.outputs.semVerStr }} created."
|
SLACK_TITLE: "AUR-bin release PR for ${{ github.event.repository.name }} ${{ github.event.release.tag_name }} created."
|
||||||
SLACK_MESSAGE: "See <${{ steps.create-pr.outputs.url }}|PR> on how to proceed."
|
SLACK_MESSAGE: "See <${{ steps.create-pr.outputs.PR_URL }}|PR> on how to proceed."
|
||||||
SLACK_FOOTER: false
|
SLACK_FOOTER: false
|
||||||
MSG_MINIMAL: true
|
MSG_MINIMAL: true
|
||||||
|
|||||||
@@ -0,0 +1,95 @@
|
|||||||
|
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'
|
||||||
|
env:
|
||||||
|
INPUT_TAG: ${{ inputs.tag }}
|
||||||
|
outputs:
|
||||||
|
url: ${{ steps.url.outputs.url}}
|
||||||
|
sha256: ${{ steps.sha256.outputs.sha256}}
|
||||||
|
steps:
|
||||||
|
- name: Determine tarball url
|
||||||
|
id: url
|
||||||
|
run: |
|
||||||
|
URL="";
|
||||||
|
if [[ -n "${INPUT_TAG}" ]]; then
|
||||||
|
URL="https://github.com/cryptomator/cryptomator/archive/refs/tags/${INPUT_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@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||||
|
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
|
||||||
|
if: github.event_name == 'release'
|
||||||
|
uses: rtCamp/action-slack-notify@e31e87e03dd19038e411e38ae27cbad084a90661 # v2.3.3
|
||||||
|
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
|
||||||
@@ -49,9 +49,9 @@ jobs:
|
|||||||
url="${INPUT_URL}"
|
url="${INPUT_URL}"
|
||||||
echo "fileName=${url##*/}" >> $GITHUB_OUTPUT
|
echo "fileName=${url##*/}" >> $GITHUB_OUTPUT
|
||||||
- name: Download file
|
- name: Download file
|
||||||
run: curl --silent --fail-with-body --proto "=https" -L "${INPUT_URL}" -o "${{steps.extractName.outputs.fileName}}"
|
run: curl "${INPUT_URL}" -L -o "${{steps.extractName.outputs.fileName}}" --fail-with-body
|
||||||
- name: Upload artifact
|
- name: Upload artifact
|
||||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
|
||||||
with:
|
with:
|
||||||
name: ${{ steps.extractName.outputs.fileName }}
|
name: ${{ steps.extractName.outputs.fileName }}
|
||||||
path: ${{ steps.extractName.outputs.fileName }}
|
path: ${{ steps.extractName.outputs.fileName }}
|
||||||
@@ -63,7 +63,7 @@ jobs:
|
|||||||
if: inputs.kaspersky
|
if: inputs.kaspersky
|
||||||
steps:
|
steps:
|
||||||
- name: Download artifact
|
- name: Download artifact
|
||||||
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
|
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
|
||||||
with:
|
with:
|
||||||
name: ${{ needs.download-file.outputs.fileName }}
|
name: ${{ needs.download-file.outputs.fileName }}
|
||||||
path: upload
|
path: upload
|
||||||
@@ -83,7 +83,7 @@ jobs:
|
|||||||
if: inputs.avast
|
if: inputs.avast
|
||||||
steps:
|
steps:
|
||||||
- name: Download artifact
|
- name: Download artifact
|
||||||
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
|
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
|
||||||
with:
|
with:
|
||||||
name: ${{ needs.download-file.outputs.fileName }}
|
name: ${{ needs.download-file.outputs.fileName }}
|
||||||
path: upload
|
path: upload
|
||||||
|
|||||||
@@ -22,14 +22,14 @@ jobs:
|
|||||||
name: Compile and Test
|
name: Compile and Test
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
|
- uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # v5.1.0
|
||||||
with:
|
with:
|
||||||
distribution: ${{ env.JAVA_DIST }}
|
distribution: ${{ env.JAVA_DIST }}
|
||||||
java-version: ${{ env.JAVA_VERSION }}
|
java-version: ${{ env.JAVA_VERSION }}
|
||||||
cache: 'maven'
|
cache: 'maven'
|
||||||
- name: Cache SonarCloud packages
|
- name: Cache SonarCloud packages
|
||||||
uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
|
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
|
||||||
with:
|
with:
|
||||||
path: ~/.sonar/cache
|
path: ~/.sonar/cache
|
||||||
key: ${{ runner.os }}-sonar
|
key: ${{ runner.os }}-sonar
|
||||||
@@ -67,7 +67,7 @@ jobs:
|
|||||||
### Other Changes 📎
|
### Other Changes 📎
|
||||||
END REPLACE-->
|
END REPLACE-->
|
||||||
|
|
||||||
For a comprehensive view of changes, read the [CHANGELOG](https://github.com/cryptomator/cryptomator/blob/develop/CHANGELOG.md).
|
Feel free to also read our [CHANGELOG.md](https://github.com/cryptomator/cryptomator/blob/develop/CHANGELOG.md).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ jobs:
|
|||||||
run: echo 'JDK_MAJOR_VERSION=${{ env.JDK_VERSION }}'.substring(0,2) >> "$env:GITHUB_ENV"
|
run: echo 'JDK_MAJOR_VERSION=${{ env.JDK_VERSION }}'.substring(0,2) >> "$env:GITHUB_ENV"
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
- name: Checkout latest JDK ${{ env.JDK_MAJOR_VERSION }}
|
- name: Checkout latest JDK ${{ env.JDK_MAJOR_VERSION }}
|
||||||
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
|
uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # v5.1.0
|
||||||
with:
|
with:
|
||||||
java-version: ${{ env.JDK_MAJOR_VERSION}}
|
java-version: ${{ env.JDK_MAJOR_VERSION}}
|
||||||
distribution: ${{ env.JDK_VENDOR }}
|
distribution: ${{ env.JDK_VENDOR }}
|
||||||
|
|||||||
@@ -23,12 +23,12 @@ on:
|
|||||||
|
|
||||||
env:
|
env:
|
||||||
JAVA_DIST: 'temurin'
|
JAVA_DIST: 'temurin'
|
||||||
JAVA_VERSION: '25.0.2+10.0.LTS'
|
JAVA_VERSION: '25.0.1+8.0.LTS'
|
||||||
DEB_BUILD_DEPENDS: 'debhelper (>=10), openjdk-25-jdk (>= 25+36), libgtk-3-0 (>= 3.20.0), libxxf86vm1, libgl1'
|
DEB_BUILD_DEPENDS: 'debhelper (>=10), openjdk-25-jdk (>= 25+36), libgtk-3-0 (>= 3.20.0), libxxf86vm1, libgl1'
|
||||||
OPENJFX_JMODS_AMD64: 'https://download2.gluonhq.com/openjfx/25.0.2/openjfx-25.0.2_linux-x64_bin-jmods.zip'
|
OPENJFX_JMODS_AMD64: 'https://download2.gluonhq.com/openjfx/25/openjfx-25_linux-x64_bin-jmods.zip'
|
||||||
OPENJFX_JMODS_AMD64_HASH: 'e0a9c29d8cf3af9b8b48848b43f87b5785bc107c53a951b19668ce05842bba1b'
|
OPENJFX_JMODS_AMD64_HASH: '96e520f48610d8ffb94ca30face1f11ffe8a977ddc1c4ff80b1a9e9f048bd94e'
|
||||||
OPENJFX_JMODS_AARCH64: 'https://download2.gluonhq.com/openjfx/25.0.2/openjfx-25.0.2_linux-aarch64_bin-jmods.zip'
|
OPENJFX_JMODS_AARCH64: 'https://download2.gluonhq.com/openjfx/25/openjfx-25_linux-aarch64_bin-jmods.zip'
|
||||||
OPENJFX_JMODS_AARCH64_HASH: 'c3408f818693cce09e59829a8e862a82c7695fdfcd585c41cfd527f5fc3fe646'
|
OPENJFX_JMODS_AARCH64_HASH: '9ad4ca7b769ca4ee6419f1e99143dd6ff812f8be4fddb46a7d7cacbeea148af4'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
get-version:
|
get-version:
|
||||||
@@ -43,7 +43,7 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
INPUT_PPAVER: ${{ inputs.ppaver }}
|
INPUT_PPAVER: ${{ inputs.ppaver }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||||
- id: deb-version
|
- id: deb-version
|
||||||
name: Determine deb-version
|
name: Determine deb-version
|
||||||
run: |
|
run: |
|
||||||
@@ -60,7 +60,7 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
DEB_BUILD_DEPENDS: ${{ env.DEB_BUILD_DEPENDS }}
|
DEB_BUILD_DEPENDS: ${{ env.DEB_BUILD_DEPENDS }}
|
||||||
- name: Setup Java
|
- name: Setup Java
|
||||||
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
|
uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # v5.1.0
|
||||||
with:
|
with:
|
||||||
distribution: ${{ env.JAVA_DIST }}
|
distribution: ${{ env.JAVA_DIST }}
|
||||||
java-version: ${{ env.JAVA_VERSION }}
|
java-version: ${{ env.JAVA_VERSION }}
|
||||||
@@ -71,11 +71,11 @@ jobs:
|
|||||||
- name: Download OpenJFX jmods
|
- name: Download OpenJFX jmods
|
||||||
id: download-jmods
|
id: download-jmods
|
||||||
run: |
|
run: |
|
||||||
curl --silent --fail-with-body --proto "=https" -L ${{ env.OPENJFX_JMODS_AMD64 }} -o openjfx-amd64.zip
|
curl -L ${{ env.OPENJFX_JMODS_AMD64 }} -o openjfx-amd64.zip
|
||||||
echo "${{ env.OPENJFX_JMODS_AMD64_HASH }} openjfx-amd64.zip" | shasum -a256 --check
|
echo "${{ env.OPENJFX_JMODS_AMD64_HASH }} openjfx-amd64.zip" | shasum -a256 --check
|
||||||
mkdir -p jmods/amd64
|
mkdir -p jmods/amd64
|
||||||
unzip -j openjfx-amd64.zip \*/javafx.base.jmod \*/javafx.controls.jmod \*/javafx.fxml.jmod \*/javafx.graphics.jmod -d jmods/amd64
|
unzip -j openjfx-amd64.zip \*/javafx.base.jmod \*/javafx.controls.jmod \*/javafx.fxml.jmod \*/javafx.graphics.jmod -d jmods/amd64
|
||||||
curl --silent --fail-with-body --proto "=https" -L ${{ env.OPENJFX_JMODS_AARCH64 }} -o openjfx-aarch64.zip
|
curl -L ${{ env.OPENJFX_JMODS_AARCH64 }} -o openjfx-aarch64.zip
|
||||||
echo "${{ env.OPENJFX_JMODS_AARCH64_HASH }} openjfx-aarch64.zip" | shasum -a256 --check
|
echo "${{ env.OPENJFX_JMODS_AARCH64_HASH }} openjfx-aarch64.zip" | shasum -a256 --check
|
||||||
mkdir -p jmods/aarch64
|
mkdir -p jmods/aarch64
|
||||||
unzip -j openjfx-aarch64.zip \*/javafx.base.jmod \*/javafx.controls.jmod \*/javafx.fxml.jmod \*/javafx.graphics.jmod -d jmods/aarch64
|
unzip -j openjfx-aarch64.zip \*/javafx.base.jmod \*/javafx.controls.jmod \*/javafx.fxml.jmod \*/javafx.graphics.jmod -d jmods/aarch64
|
||||||
@@ -143,7 +143,7 @@ jobs:
|
|||||||
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
|
||||||
- name: Upload artifacts
|
- name: Upload artifacts
|
||||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
|
||||||
with:
|
with:
|
||||||
name: linux-deb-package
|
name: linux-deb-package
|
||||||
path: |
|
path: |
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
check-dependencies:
|
check-dependencies:
|
||||||
uses: skymatic/workflows/.github/workflows/run-dependency-check.yml@957d3c2c08c56855fdac41e5afb9a7aca8c30dd9 # v3.0.3
|
uses: skymatic/workflows/.github/workflows/run-dependency-check.yml@1074588008ae3326a2221ea451783280518f0366 # v3.0.1
|
||||||
with:
|
with:
|
||||||
runner-os: 'ubuntu-latest'
|
runner-os: 'ubuntu-latest'
|
||||||
java-distribution: 'temurin'
|
java-distribution: 'temurin'
|
||||||
@@ -16,4 +16,4 @@ jobs:
|
|||||||
nvd-api-key: ${{ secrets.NVD_API_KEY }}
|
nvd-api-key: ${{ secrets.NVD_API_KEY }}
|
||||||
ossindex-username: ${{ secrets.OSSINDEX_USERNAME }}
|
ossindex-username: ${{ secrets.OSSINDEX_USERNAME }}
|
||||||
ossindex-token: ${{ secrets.OSSINDEX_API_TOKEN }}
|
ossindex-token: ${{ secrets.OSSINDEX_API_TOKEN }}
|
||||||
slack-webhook-url: ${{ secrets.SLACK_WEBHOOK_CRYPTOMATOR_DESKTOP }}
|
slack-webhook-url: ${{ secrets.SLACK_WEBHOOK_URL }}
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ jobs:
|
|||||||
INTERVAL: 900
|
INTERVAL: 900
|
||||||
JSON_DATA: ${{ steps.get-stats.outputs.result }}
|
JSON_DATA: ${{ steps.get-stats.outputs.result }}
|
||||||
- name: Upload Results
|
- name: Upload Results
|
||||||
uses: fjogeleit/http-request-action@551353b829c3646756b2ec2b3694f819d7957495 # v2.0.0
|
uses: fjogeleit/http-request-action@c0b95d02a088b47c1f2f4db04fd8af8bd19eee54 # v1.16.6
|
||||||
with:
|
with:
|
||||||
url: 'https://graphite-us-central1.grafana.net/metrics'
|
url: 'https://graphite-us-central1.grafana.net/metrics'
|
||||||
method: 'POST'
|
method: 'POST'
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ jobs:
|
|||||||
- name: Download source tarball and compute checksum
|
- name: Download source tarball and compute checksum
|
||||||
id: sha512
|
id: sha512
|
||||||
run: |
|
run: |
|
||||||
curl --silent --fail-with-body --proto "=https" -L -H "Accept: application/vnd.github+json" ${{ steps.url.outputs.url }} --output cryptomator.tar.gz
|
curl --silent --fail-with-body -L -H "Accept: application/vnd.github+json" ${{ steps.url.outputs.url }} --output cryptomator.tar.gz
|
||||||
TARBALL_SHA512=$(sha512sum cryptomator.tar.gz | cut -d ' ' -f1)
|
TARBALL_SHA512=$(sha512sum cryptomator.tar.gz | cut -d ' ' -f1)
|
||||||
echo "sha512=${TARBALL_SHA512}" >> "$GITHUB_OUTPUT"
|
echo "sha512=${TARBALL_SHA512}" >> "$GITHUB_OUTPUT"
|
||||||
flathub:
|
flathub:
|
||||||
@@ -43,7 +43,7 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
FLATHUB_PR_URL: tbd
|
FLATHUB_PR_URL: tbd
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||||
with:
|
with:
|
||||||
repository: 'flathub/org.cryptomator.Cryptomator'
|
repository: 'flathub/org.cryptomator.Cryptomator'
|
||||||
token: ${{ secrets.CRYPTOBOT_PR_TOKEN }}
|
token: ${{ secrets.CRYPTOBOT_PR_TOKEN }}
|
||||||
|
|||||||
@@ -35,11 +35,11 @@ jobs:
|
|||||||
revNum: ${{ steps.versions.outputs.revNum }}
|
revNum: ${{ steps.versions.outputs.revNum }}
|
||||||
type: ${{ steps.versions.outputs.type}}
|
type: ${{ steps.versions.outputs.type}}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- name: Setup Java
|
- name: Setup Java
|
||||||
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
|
uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # v5.1.0
|
||||||
with:
|
with:
|
||||||
distribution: ${{ env.JAVA_DIST }}
|
distribution: ${{ env.JAVA_DIST }}
|
||||||
java-version: ${{ env.JAVA_VERSION }}
|
java-version: ${{ env.JAVA_VERSION }}
|
||||||
|
|||||||
@@ -1,200 +0,0 @@
|
|||||||
name: Build Arch package
|
|
||||||
|
|
||||||
on:
|
|
||||||
release:
|
|
||||||
types: [published]
|
|
||||||
workflow_dispatch:
|
|
||||||
inputs:
|
|
||||||
version:
|
|
||||||
description: 'Version'
|
|
||||||
required: false
|
|
||||||
create-pr:
|
|
||||||
description: 'Create a PR for aur repo'
|
|
||||||
type: boolean
|
|
||||||
default: false
|
|
||||||
push:
|
|
||||||
branches-ignore:
|
|
||||||
- 'dependabot/**'
|
|
||||||
paths:
|
|
||||||
- '.github/workflows/linux-makepkg.yml'
|
|
||||||
- 'dist/linux/makepkg/**'
|
|
||||||
- 'dist/linux/common/**'
|
|
||||||
- 'dist/linux/resources/**'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
get-version:
|
|
||||||
uses: ./.github/workflows/get-version.yml
|
|
||||||
with:
|
|
||||||
version: ${{ inputs.version }}
|
|
||||||
|
|
||||||
makepkg:
|
|
||||||
name: Build with makepkg
|
|
||||||
needs: [get-version]
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
container:
|
|
||||||
image: archlinux:base-devel
|
|
||||||
env:
|
|
||||||
PKGDEST: ${{ github.workspace }}/pkgdest
|
|
||||||
SRCDEST: ${{ github.workspace }}/srcdest
|
|
||||||
steps:
|
|
||||||
- name: Prepare pacman
|
|
||||||
run: |
|
|
||||||
pacman-key --init
|
|
||||||
pacman-key --populate archlinux
|
|
||||||
pacman -Syu --noconfirm --needed git base-devel sudo gnupg maven unzip
|
|
||||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
||||||
with:
|
|
||||||
path: cryptomator
|
|
||||||
- name: Create build user
|
|
||||||
run: |
|
|
||||||
useradd -m builder
|
|
||||||
echo 'builder ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers.d/builder
|
|
||||||
chown -R builder:builder "$GITHUB_WORKSPACE"
|
|
||||||
install -d -m 0755 -o builder -g builder "$PKGDEST" "$SRCDEST"
|
|
||||||
- name: Prepare PKGBUILD
|
|
||||||
# cannot use github.workspace due to https://github.com/actions/runner/issues/2058
|
|
||||||
run: |
|
|
||||||
export SOURCES="${SOURCES_1}${GITHUB_WORKSPACE}${SOURCES_2}"
|
|
||||||
envsubst '$PKG_VERSION $PKG_RELEASE $SOURCES $SOURCES_SHA' < cryptomator/dist/linux/makepkg/PKGBUILD.template > PKGBUILD
|
|
||||||
env:
|
|
||||||
PKG_VERSION: ${{ needs.get-version.outputs.semVerNum }}
|
|
||||||
PKG_RELEASE: 1
|
|
||||||
SOURCES_1: '"${_src_app_dir}::git+file://'
|
|
||||||
SOURCES_2: '/cryptomator"'
|
|
||||||
SOURCES_SHA: "'SKIP'"
|
|
||||||
- name: Build package with makepkg
|
|
||||||
run: >
|
|
||||||
sudo -u builder
|
|
||||||
env PKGDEST="$PKGDEST" SRCDEST="$SRCDEST"
|
|
||||||
makepkg --syncdeps --cleanbuild --noconfirm --log
|
|
||||||
- uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
|
||||||
with:
|
|
||||||
name: arch-package
|
|
||||||
if-no-files-found: error
|
|
||||||
path: |
|
|
||||||
${{ env.PKGDEST }}/*.pkg.tar.zst
|
|
||||||
- uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
|
||||||
with:
|
|
||||||
name: pkgbuild-file
|
|
||||||
if-no-files-found: error
|
|
||||||
path: |
|
|
||||||
cryptomator/dist/linux/makepkg/PKGBUILD.template
|
|
||||||
|
|
||||||
create-pr:
|
|
||||||
name: Create PR for aur repo
|
|
||||||
if: github.event_name == 'workflow_dispatch' && inputs.create-pr || github.event_name == 'release' && needs.get-version.outputs.versionType == 'stable'
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: [get-version, makepkg]
|
|
||||||
container:
|
|
||||||
image: archlinux:base-devel
|
|
||||||
env:
|
|
||||||
PKGDEST: ${{ github.workspace }}/pkgdest
|
|
||||||
SRCDEST: ${{ github.workspace }}/srcdest
|
|
||||||
steps:
|
|
||||||
- name: Prepare pacman
|
|
||||||
run: |
|
|
||||||
pacman-key --init
|
|
||||||
pacman-key --populate archlinux
|
|
||||||
pacman -Syu --noconfirm --needed git base-devel sudo gnupg maven unzip github-cli curl
|
|
||||||
- name: Download source tarball and compute checksum
|
|
||||||
id: sha256
|
|
||||||
run: |
|
|
||||||
URL="https://github.com/cryptomator/cryptomator/archive/refs/tags/${TAG}.tar.gz"
|
|
||||||
curl --silent --fail-with-body --proto "=https" -L -H "Accept: application/vnd.github+json" ${URL} --output cryptomator.tar.gz
|
|
||||||
TARBALL_SHA256=$(sha256sum cryptomator.tar.gz | cut -d ' ' -f1)
|
|
||||||
echo "value=${TARBALL_SHA256}" >> "$GITHUB_OUTPUT"
|
|
||||||
env:
|
|
||||||
TAG: ${{ needs.get-version.outputs.semVerStr || github.event.release.tag_name }}
|
|
||||||
- name: Checkout cryptomator/aur repo
|
|
||||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
||||||
with:
|
|
||||||
repository: 'cryptomator/aur'
|
|
||||||
token: ${{ secrets.CRYPTOBOT_PR_TOKEN }}
|
|
||||||
- name: Create build user
|
|
||||||
run: |
|
|
||||||
useradd -m builder
|
|
||||||
echo 'builder ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers.d/builder
|
|
||||||
chown -R builder:builder "$GITHUB_WORKSPACE"
|
|
||||||
install -d -m 0755 -o builder -g builder "$PKGDEST" "$SRCDEST"
|
|
||||||
- name: Import Cryptomator release signing key
|
|
||||||
# try first ubuntu. on failure try openpgp keyservers
|
|
||||||
run: >
|
|
||||||
sudo -u builder gpg --batch --keyserver hkps://keyserver.ubuntu.com --recv-keys 58117AFA1F85B3EEC154677D615D449FE6E6A235
|
|
||||||
|| sudo -u builder gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys 58117AFA1F85B3EEC154677D615D449FE6E6A235
|
|
||||||
- name: Checkout release branch
|
|
||||||
run: |
|
|
||||||
git config --global safe.directory '*'
|
|
||||||
git checkout -b release/${VERSION}
|
|
||||||
env:
|
|
||||||
VERSION: ${{ needs.get-version.outputs.semVerStr }}
|
|
||||||
- name: Determine pkgrel
|
|
||||||
id: pkgrel
|
|
||||||
run: |
|
|
||||||
TARGET_VERSION='${{ needs.get-version.outputs.semVerStr }}'
|
|
||||||
CURRENT_VERSION="$(sed -nE 's/^pkgver=(.*)$/\1/p' PKGBUILD | head -n1)"
|
|
||||||
CURRENT_REL="$(sed -nE 's/^pkgrel=([0-9]+).*$/\1/p' PKGBUILD | head -n1)"
|
|
||||||
|
|
||||||
if [[ "$CURRENT_VERSION" == "$TARGET_VERSION" && "$CURRENT_REL" =~ ^[0-9]+$ ]]; then
|
|
||||||
NEXT_REL=$((CURRENT_REL + 1))
|
|
||||||
else
|
|
||||||
NEXT_REL=1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "value=${NEXT_REL}" >> "$GITHUB_OUTPUT"
|
|
||||||
echo "dist-version=${VERSION}-${NEXT_REL}" >> "$GITHUB_OUTPUT"
|
|
||||||
env:
|
|
||||||
VERSION: ${{ needs.get-version.outputs.semVerStr }}
|
|
||||||
- name: Download PKGBUILD template
|
|
||||||
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
|
|
||||||
with:
|
|
||||||
name: pkgbuild-file
|
|
||||||
- name: Prepare PKGBUILD
|
|
||||||
run: |
|
|
||||||
envsubst '$PKG_VERSION $PKG_RELEASE $SOURCES $SOURCES_SHA' < PKGBUILD.template > PKGBUILD
|
|
||||||
sudo -u builder makepkg --printsrcinfo > .SRCINFO
|
|
||||||
env:
|
|
||||||
PKG_VERSION: ${{ needs.get-version.outputs.semVerNum }}
|
|
||||||
PKG_RELEASE: ${{ steps.pkgrel.outputs.value }}
|
|
||||||
SOURCES: |-
|
|
||||||
"cryptomator-${pkgver//_/-}.tar.gz::https://github.com/cryptomator/cryptomator/archive/refs/tags/${pkgver//_/-}.tar.gz"
|
|
||||||
"cryptomator-${pkgver//_/-}.tar.gz.asc::https://github.com/cryptomator/cryptomator/releases/download/${pkgver//_/-}/cryptomator-${pkgver//_/-}.tar.gz.asc"
|
|
||||||
SOURCES_SHA: |-
|
|
||||||
'${{steps.sha256.outputs.value}}'
|
|
||||||
'SKIP'
|
|
||||||
- name: Build package with makepkg
|
|
||||||
run: >
|
|
||||||
sudo -u builder
|
|
||||||
env PKGDEST="$PKGDEST" SRCDEST="$SRCDEST"
|
|
||||||
makepkg --syncdeps --cleanbuild --noconfirm --log
|
|
||||||
- name: Commit and push
|
|
||||||
run: |
|
|
||||||
git config user.name "cryptobot"
|
|
||||||
git config user.email "cryptobot@users.noreply.github.com"
|
|
||||||
git config push.autoSetupRemote true
|
|
||||||
git stage PKGBUILD .SRCINFO
|
|
||||||
git commit -m "Prepare release ${DIST_VERSION}"
|
|
||||||
git push
|
|
||||||
env:
|
|
||||||
DIST_VERSION: ${{ steps.pkgrel.outputs.dist-version }}
|
|
||||||
- name: Create pull request
|
|
||||||
id: create-pr
|
|
||||||
run: |
|
|
||||||
printf "Created by $GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID" > pr_body.md
|
|
||||||
PR_URL=$(gh pr create --title "Release $DIST_VERSION" --body-file pr_body.md)
|
|
||||||
echo "url=$PR_URL" >> "$GITHUB_OUTPUT"
|
|
||||||
env:
|
|
||||||
DIST_VERSION: ${{ steps.pkgrel.outputs.dist-version }}
|
|
||||||
GH_TOKEN: ${{ secrets.CRYPTOBOT_PR_TOKEN }}
|
|
||||||
- name: Slack Notification
|
|
||||||
if: github.event_name == 'release'
|
|
||||||
uses: rtCamp/action-slack-notify@e31e87e03dd19038e411e38ae27cbad084a90661 # v2.3.3
|
|
||||||
env:
|
|
||||||
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_CRYPTOMATOR_DESKTOP }}
|
|
||||||
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 }} ${{ steps.pkgrel.outputs.dist-version }} ."
|
|
||||||
SLACK_MESSAGE: "See <${{ steps.create-pr.outputs.url }}|PR> on how to proceed."
|
|
||||||
SLACK_FOOTER: false
|
|
||||||
MSG_MINIMAL: true
|
|
||||||
@@ -24,7 +24,7 @@ on:
|
|||||||
|
|
||||||
env:
|
env:
|
||||||
JAVA_DIST: 'temurin'
|
JAVA_DIST: 'temurin'
|
||||||
JAVA_VERSION: '25.0.2+10.0.LTS'
|
JAVA_VERSION: '25.0.1+8.0.LTS'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
get-version:
|
get-version:
|
||||||
@@ -44,12 +44,12 @@ jobs:
|
|||||||
architecture: x64
|
architecture: x64
|
||||||
output-suffix: x64
|
output-suffix: x64
|
||||||
fuse-lib: macFUSE
|
fuse-lib: macFUSE
|
||||||
openjfx-url: 'https://download2.gluonhq.com/openjfx/25.0.2/openjfx-25.0.2_osx-x64_bin-jmods.zip'
|
openjfx-url: 'https://download2.gluonhq.com/openjfx/25/openjfx-25_osx-x64_bin-jmods.zip'
|
||||||
openjfx-sha: '0b4d8463f03901b7425d94628e4116b7078abb8dd540fbec415266fac20bda5c'
|
openjfx-sha: '0eba73fb28a24c845175d16fa2f8c081c936ce6de1be9b79eb6119fa32e53d52'
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||||
- name: Setup Java
|
- name: Setup Java
|
||||||
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
|
uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # v5.1.0
|
||||||
with:
|
with:
|
||||||
distribution: ${{ env.JAVA_DIST }}
|
distribution: ${{ env.JAVA_DIST }}
|
||||||
java-version: ${{ env.JAVA_VERSION }}
|
java-version: ${{ env.JAVA_VERSION }}
|
||||||
@@ -59,7 +59,7 @@ jobs:
|
|||||||
- name: Download OpenJFX jmods
|
- name: Download OpenJFX jmods
|
||||||
id: download-jmods
|
id: download-jmods
|
||||||
run: |
|
run: |
|
||||||
curl --silent --fail-with-body --proto "=https" -L ${{ matrix.openjfx-url }} -o openjfx-jmods.zip
|
curl -L ${{ matrix.openjfx-url }} -o openjfx-jmods.zip
|
||||||
echo "${{ matrix.openjfx-sha }} *openjfx-jmods.zip" | shasum -a256 --check
|
echo "${{ matrix.openjfx-sha }} *openjfx-jmods.zip" | shasum -a256 --check
|
||||||
mkdir -p openjfx-jmods/
|
mkdir -p openjfx-jmods/
|
||||||
unzip -jo openjfx-jmods.zip \*/javafx.base.jmod \*/javafx.controls.jmod \*/javafx.fxml.jmod \*/javafx.graphics.jmod -d openjfx-jmods
|
unzip -jo openjfx-jmods.zip \*/javafx.base.jmod \*/javafx.controls.jmod \*/javafx.fxml.jmod \*/javafx.graphics.jmod -d openjfx-jmods
|
||||||
@@ -128,8 +128,8 @@ jobs:
|
|||||||
--java-options "-Dapple.awt.enableTemplateImages=true"
|
--java-options "-Dapple.awt.enableTemplateImages=true"
|
||||||
--java-options "-Dsun.java2d.metal=true"
|
--java-options "-Dsun.java2d.metal=true"
|
||||||
--java-options "-Dcryptomator.appVersion=\"${{ needs.get-version.outputs.semVerStr }}\""
|
--java-options "-Dcryptomator.appVersion=\"${{ needs.get-version.outputs.semVerStr }}\""
|
||||||
--java-options "-Dcryptomator.adminConfigPath=\"/Library/Application Support/Cryptomator/config.properties\""
|
|
||||||
--java-options "-Dcryptomator.logDir=\"@{userhome}/Library/Logs/Cryptomator\""
|
--java-options "-Dcryptomator.logDir=\"@{userhome}/Library/Logs/Cryptomator\""
|
||||||
|
--java-options "-Dcryptomator.pluginDir=\"@{userhome}/Library/Application Support/Cryptomator/Plugins\""
|
||||||
--java-options "-Dcryptomator.settingsPath=\"@{userhome}/Library/Application Support/Cryptomator/settings.json\""
|
--java-options "-Dcryptomator.settingsPath=\"@{userhome}/Library/Application Support/Cryptomator/settings.json\""
|
||||||
--java-options "-Dcryptomator.p12Path=\"@{userhome}/Library/Application Support/Cryptomator/key.p12\""
|
--java-options "-Dcryptomator.p12Path=\"@{userhome}/Library/Application Support/Cryptomator/key.p12\""
|
||||||
--java-options "-Dcryptomator.ipcSocketPath=\"@{userhome}/Library/Application Support/Cryptomator/ipc.socket\""
|
--java-options "-Dcryptomator.ipcSocketPath=\"@{userhome}/Library/Application Support/Cryptomator/ipc.socket\""
|
||||||
@@ -144,7 +144,6 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
mv appdir/Cryptomator.app Cryptomator.app
|
mv appdir/Cryptomator.app Cryptomator.app
|
||||||
mv dist/mac/resources/Cryptomator-Vault.icns Cryptomator.app/Contents/Resources/
|
mv dist/mac/resources/Cryptomator-Vault.icns Cryptomator.app/Contents/Resources/
|
||||||
cp dist/mac/resources/Assets.car Cryptomator.app/Contents/Resources/
|
|
||||||
sed -i '' "s|###BUNDLE_SHORT_VERSION_STRING###|${VERSION_NO}|g" Cryptomator.app/Contents/Info.plist
|
sed -i '' "s|###BUNDLE_SHORT_VERSION_STRING###|${VERSION_NO}|g" Cryptomator.app/Contents/Info.plist
|
||||||
sed -i '' "s|###BUNDLE_VERSION###|${REVISION_NO}|g" Cryptomator.app/Contents/Info.plist
|
sed -i '' "s|###BUNDLE_VERSION###|${REVISION_NO}|g" Cryptomator.app/Contents/Info.plist
|
||||||
echo -n "$PROVISIONING_PROFILE_BASE64" | base64 --decode --output Cryptomator.app/Contents/embedded.provisionprofile
|
echo -n "$PROVISIONING_PROFILE_BASE64" | base64 --decode --output Cryptomator.app/Contents/embedded.provisionprofile
|
||||||
@@ -152,6 +151,20 @@ jobs:
|
|||||||
VERSION_NO: ${{ needs.get-version.outputs.semVerNum }}
|
VERSION_NO: ${{ needs.get-version.outputs.semVerNum }}
|
||||||
REVISION_NO: ${{ needs.get-version.outputs.revNum }}
|
REVISION_NO: ${{ needs.get-version.outputs.revNum }}
|
||||||
PROVISIONING_PROFILE_BASE64: ${{ secrets.MACOS_PROVISIONING_PROFILE_BASE64 }}
|
PROVISIONING_PROFILE_BASE64: ${{ secrets.MACOS_PROVISIONING_PROFILE_BASE64 }}
|
||||||
|
- name: Build and install DockTilePlugin
|
||||||
|
env:
|
||||||
|
DERIVED_DATA_PATH: dist/mac/DockTilePlugin/build
|
||||||
|
run: |
|
||||||
|
xcodebuild -project dist/mac/DockTilePlugin/DockTilePlugin.xcodeproj \
|
||||||
|
-scheme DockTilePlugin \
|
||||||
|
-configuration Release \
|
||||||
|
-destination "platform=macOS,arch=x86_64" \
|
||||||
|
-derivedDataPath ${DERIVED_DATA_PATH} \
|
||||||
|
-quiet \
|
||||||
|
clean build
|
||||||
|
mkdir -p Cryptomator.app/Contents/PlugIns
|
||||||
|
cp -R ${DERIVED_DATA_PATH}/Build/Products/Release/Cryptomator.docktileplugin Cryptomator.app/Contents/PlugIns/
|
||||||
|
rm -rf ${DERIVED_DATA_PATH}
|
||||||
- name: Generate license for dmg
|
- name: Generate license for dmg
|
||||||
run: >
|
run: >
|
||||||
mvn -B license:add-third-party
|
mvn -B license:add-third-party
|
||||||
@@ -270,7 +283,7 @@ jobs:
|
|||||||
run: security delete-keychain $RUNNER_TEMP/codesign.keychain-db
|
run: security delete-keychain $RUNNER_TEMP/codesign.keychain-db
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
- name: Upload artifacts
|
- name: Upload artifacts
|
||||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
|
||||||
with:
|
with:
|
||||||
name: dmg-${{ matrix.output-suffix }}
|
name: dmg-${{ matrix.output-suffix }}
|
||||||
path: |
|
path: |
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ on:
|
|||||||
|
|
||||||
env:
|
env:
|
||||||
JAVA_DIST: 'temurin'
|
JAVA_DIST: 'temurin'
|
||||||
JAVA_VERSION: '25.0.2+10.0.LTS'
|
JAVA_VERSION: '25.0.1+8.0.LTS'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
get-version:
|
get-version:
|
||||||
@@ -42,12 +42,12 @@ 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/25.0.2/openjfx-25.0.2_osx-aarch64_bin-jmods.zip'
|
openjfx-url: 'https://download2.gluonhq.com/openjfx/25/openjfx-25_osx-aarch64_bin-jmods.zip'
|
||||||
openjfx-sha: '4cd258001c75af7047005c5c891e2400ed11d24fbb09412324c0cbaf8b503c5a'
|
openjfx-sha: '13f8c0513c40c95881479fbcf0465a29a60217393fb0656f5e4eab78a9442fba'
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||||
- name: Setup Java
|
- name: Setup Java
|
||||||
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
|
uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # v5.1.0
|
||||||
with:
|
with:
|
||||||
distribution: ${{ env.JAVA_DIST }}
|
distribution: ${{ env.JAVA_DIST }}
|
||||||
java-version: ${{ env.JAVA_VERSION }}
|
java-version: ${{ env.JAVA_VERSION }}
|
||||||
@@ -57,7 +57,7 @@ jobs:
|
|||||||
- name: Download OpenJFX jmods
|
- name: Download OpenJFX jmods
|
||||||
id: download-jmods
|
id: download-jmods
|
||||||
run: |
|
run: |
|
||||||
curl --silent --fail-with-body --proto "=https" -L ${{ matrix.openjfx-url }} -o openjfx-jmods.zip
|
curl -L ${{ matrix.openjfx-url }} -o openjfx-jmods.zip
|
||||||
echo "${{ matrix.openjfx-sha }} *openjfx-jmods.zip" | shasum -a256 --check
|
echo "${{ matrix.openjfx-sha }} *openjfx-jmods.zip" | shasum -a256 --check
|
||||||
mkdir -p openjfx-jmods/
|
mkdir -p openjfx-jmods/
|
||||||
unzip -jo openjfx-jmods.zip \*/javafx.base.jmod \*/javafx.controls.jmod \*/javafx.fxml.jmod \*/javafx.graphics.jmod -d openjfx-jmods
|
unzip -jo openjfx-jmods.zip \*/javafx.base.jmod \*/javafx.controls.jmod \*/javafx.fxml.jmod \*/javafx.graphics.jmod -d openjfx-jmods
|
||||||
@@ -126,8 +126,8 @@ jobs:
|
|||||||
--java-options "-Dapple.awt.enableTemplateImages=true"
|
--java-options "-Dapple.awt.enableTemplateImages=true"
|
||||||
--java-options "-Dsun.java2d.metal=true"
|
--java-options "-Dsun.java2d.metal=true"
|
||||||
--java-options "-Dcryptomator.appVersion=\"${{ needs.get-version.outputs.semVerStr }}\""
|
--java-options "-Dcryptomator.appVersion=\"${{ needs.get-version.outputs.semVerStr }}\""
|
||||||
--java-options "-Dcryptomator.adminConfigPath=\"/Library/Application Support/Cryptomator/config.properties\""
|
|
||||||
--java-options "-Dcryptomator.logDir=\"@{userhome}/Library/Logs/Cryptomator\""
|
--java-options "-Dcryptomator.logDir=\"@{userhome}/Library/Logs/Cryptomator\""
|
||||||
|
--java-options "-Dcryptomator.pluginDir=\"@{userhome}/Library/Application Support/Cryptomator/Plugins\""
|
||||||
--java-options "-Dcryptomator.settingsPath=\"@{userhome}/Library/Application Support/Cryptomator/settings.json\""
|
--java-options "-Dcryptomator.settingsPath=\"@{userhome}/Library/Application Support/Cryptomator/settings.json\""
|
||||||
--java-options "-Dcryptomator.p12Path=\"@{userhome}/Library/Application Support/Cryptomator/key.p12\""
|
--java-options "-Dcryptomator.p12Path=\"@{userhome}/Library/Application Support/Cryptomator/key.p12\""
|
||||||
--java-options "-Dcryptomator.ipcSocketPath=\"@{userhome}/Library/Application Support/Cryptomator/ipc.socket\""
|
--java-options "-Dcryptomator.ipcSocketPath=\"@{userhome}/Library/Application Support/Cryptomator/ipc.socket\""
|
||||||
@@ -143,7 +143,6 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
mv appdir/Cryptomator.app Cryptomator.app
|
mv appdir/Cryptomator.app Cryptomator.app
|
||||||
mv dist/mac/resources/Cryptomator-Vault.icns Cryptomator.app/Contents/Resources/
|
mv dist/mac/resources/Cryptomator-Vault.icns Cryptomator.app/Contents/Resources/
|
||||||
cp dist/mac/resources/Assets.car Cryptomator.app/Contents/Resources/
|
|
||||||
sed -i '' "s|###BUNDLE_SHORT_VERSION_STRING###|${VERSION_NO}|g" Cryptomator.app/Contents/Info.plist
|
sed -i '' "s|###BUNDLE_SHORT_VERSION_STRING###|${VERSION_NO}|g" Cryptomator.app/Contents/Info.plist
|
||||||
sed -i '' "s|###BUNDLE_VERSION###|${REVISION_NO}|g" Cryptomator.app/Contents/Info.plist
|
sed -i '' "s|###BUNDLE_VERSION###|${REVISION_NO}|g" Cryptomator.app/Contents/Info.plist
|
||||||
echo -n "$PROVISIONING_PROFILE_BASE64" | base64 --decode --output Cryptomator.app/Contents/embedded.provisionprofile
|
echo -n "$PROVISIONING_PROFILE_BASE64" | base64 --decode --output Cryptomator.app/Contents/embedded.provisionprofile
|
||||||
@@ -151,6 +150,20 @@ jobs:
|
|||||||
VERSION_NO: ${{ needs.get-version.outputs.semVerNum }}
|
VERSION_NO: ${{ needs.get-version.outputs.semVerNum }}
|
||||||
REVISION_NO: ${{ needs.get-version.outputs.revNum }}
|
REVISION_NO: ${{ needs.get-version.outputs.revNum }}
|
||||||
PROVISIONING_PROFILE_BASE64: ${{ secrets.MACOS_PROVISIONING_PROFILE_BASE64 }}
|
PROVISIONING_PROFILE_BASE64: ${{ secrets.MACOS_PROVISIONING_PROFILE_BASE64 }}
|
||||||
|
- name: Build and install DockTilePlugin
|
||||||
|
env:
|
||||||
|
DERIVED_DATA_PATH: dist/mac/DockTilePlugin/build
|
||||||
|
run: |
|
||||||
|
xcodebuild -project dist/mac/DockTilePlugin/DockTilePlugin.xcodeproj \
|
||||||
|
-scheme DockTilePlugin \
|
||||||
|
-configuration Release \
|
||||||
|
-destination "platform=macOS,arch=arm64" \
|
||||||
|
-derivedDataPath ${DERIVED_DATA_PATH} \
|
||||||
|
-quiet \
|
||||||
|
clean build
|
||||||
|
mkdir -p Cryptomator.app/Contents/PlugIns
|
||||||
|
cp -R ${DERIVED_DATA_PATH}/Build/Products/Release/Cryptomator.docktileplugin Cryptomator.app/Contents/PlugIns/
|
||||||
|
rm -rf ${DERIVED_DATA_PATH}
|
||||||
- name: Generate license for dmg
|
- name: Generate license for dmg
|
||||||
run: >
|
run: >
|
||||||
mvn -B license:add-third-party
|
mvn -B license:add-third-party
|
||||||
@@ -269,7 +282,7 @@ jobs:
|
|||||||
run: security delete-keychain $RUNNER_TEMP/codesign.keychain-db
|
run: security delete-keychain $RUNNER_TEMP/codesign.keychain-db
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
- name: Upload artifacts
|
- name: Upload artifacts
|
||||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
|
||||||
with:
|
with:
|
||||||
name: dmg-${{ matrix.output-suffix }}
|
name: dmg-${{ matrix.output-suffix }}
|
||||||
path: |
|
path: |
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ jobs:
|
|||||||
issues: write
|
issues: write
|
||||||
pull-requests: write
|
pull-requests: write
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/stale@b5d41d4e1d5dceea10e7104786b73624c18a190f # v10.2.0
|
- uses: actions/stale@997185467fa4f803885201cee163a9f38240193d # v10.1.1
|
||||||
with:
|
with:
|
||||||
days-before-stale: 14
|
days-before-stale: 14
|
||||||
days-before-close: 0
|
days-before-close: 0
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- name: Download source tarball
|
- name: Download source tarball
|
||||||
run: |
|
run: |
|
||||||
curl --silent --fail-with-body --proto "=https" -L -H "Accept: application/vnd.github+json" https://github.com/cryptomator/cryptomator/archive/refs/tags/${{ github.event.release.tag_name }}.tar.gz --output cryptomator-${{ github.event.release.tag_name }}.tar.gz
|
curl -L -H "Accept: application/vnd.github+json" https://github.com/cryptomator/cryptomator/archive/refs/tags/${{ github.event.release.tag_name }}.tar.gz --output cryptomator-${{ github.event.release.tag_name }}.tar.gz
|
||||||
- name: Sign source tarball with key 615D449FE6E6A235
|
- name: Sign source tarball with key 615D449FE6E6A235
|
||||||
run: |
|
run: |
|
||||||
echo "${GPG_PRIVATE_KEY}" | gpg --batch --quiet --import
|
echo "${GPG_PRIVATE_KEY}" | gpg --batch --quiet --import
|
||||||
@@ -28,7 +28,7 @@ jobs:
|
|||||||
- name: Slack Notification
|
- name: Slack Notification
|
||||||
uses: rtCamp/action-slack-notify@e31e87e03dd19038e411e38ae27cbad084a90661 # v2.3.3
|
uses: rtCamp/action-slack-notify@e31e87e03dd19038e411e38ae27cbad084a90661 # v2.3.3
|
||||||
env:
|
env:
|
||||||
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_CRYPTOMATOR_DESKTOP }}
|
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }}
|
||||||
SLACK_USERNAME: 'Cryptobot'
|
SLACK_USERNAME: 'Cryptobot'
|
||||||
SLACK_ICON: false
|
SLACK_ICON: false
|
||||||
SLACK_ICON_EMOJI: ':bot:'
|
SLACK_ICON_EMOJI: ':bot:'
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ jobs:
|
|||||||
name: Compile and Test
|
name: Compile and Test
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
|
- uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # v5.1.0
|
||||||
with:
|
with:
|
||||||
distribution: ${{ env.JAVA_DIST }}
|
distribution: ${{ env.JAVA_DIST }}
|
||||||
java-version: ${{ env.JAVA_VERSION }}
|
java-version: ${{ env.JAVA_VERSION }}
|
||||||
|
|||||||
@@ -19,9 +19,9 @@ jobs:
|
|||||||
name: Validate commits pushed to release/hotfix branch to fulfill release requirements
|
name: Validate commits pushed to release/hotfix branch to fulfill release requirements
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||||
- name: Setup Java
|
- name: Setup Java
|
||||||
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
|
uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # v5.1.0
|
||||||
with:
|
with:
|
||||||
distribution: ${{ env.JAVA_DIST }}
|
distribution: ${{ env.JAVA_DIST }}
|
||||||
java-version: ${{ env.JAVA_VERSION }}
|
java-version: ${{ env.JAVA_VERSION }}
|
||||||
@@ -43,14 +43,13 @@ jobs:
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
- name: Validate release in org.cryptomator.Cryptomator.metainfo.xml file
|
- name: Validate release in org.cryptomator.Cryptomator.metainfo.xml file
|
||||||
if: ${{ ! (contains(github.event.head_commit.message, '[skip metadata check]') || contains(github.event.head_commit.message, '[metadata check skip]')) }}
|
|
||||||
run: |
|
run: |
|
||||||
if ! grep -q "<release date=\".*\" version=\"${{ steps.validate-pom-version.outputs.semVerStr }}\">" dist/linux/common/org.cryptomator.Cryptomator.metainfo.xml; then
|
if ! grep -q "<release date=\".*\" version=\"${{ steps.validate-pom-version.outputs.semVerStr }}\">" dist/linux/common/org.cryptomator.Cryptomator.metainfo.xml; then
|
||||||
echo "Release not set in dist/linux/common/org.cryptomator.Cryptomator.metainfo.xml"
|
echo "Release not set in dist/linux/common/org.cryptomator.Cryptomator.metainfo.xml"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
- name: Cache NVD DB
|
- name: Cache NVD DB
|
||||||
uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
|
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
|
||||||
with:
|
with:
|
||||||
path: ~/.m2/repository/org/owasp/dependency-check-data/
|
path: ~/.m2/repository/org/owasp/dependency-check-data/
|
||||||
key: dependency-check-${{ github.run_id }}
|
key: dependency-check-${{ github.run_id }}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ jobs:
|
|||||||
issues: write
|
issues: write
|
||||||
pull-requests: write
|
pull-requests: write
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/stale@b5d41d4e1d5dceea10e7104786b73624c18a190f # v10.2.0
|
- uses: actions/stale@997185467fa4f803885201cee163a9f38240193d # v10.1.1
|
||||||
with:
|
with:
|
||||||
days-before-stale: 365
|
days-before-stale: 365
|
||||||
days-before-close: 90
|
days-before-close: 90
|
||||||
|
|||||||
@@ -22,12 +22,11 @@ on:
|
|||||||
|
|
||||||
|
|
||||||
env:
|
env:
|
||||||
OPENJFX_JMODS_AMD64: 'https://download2.gluonhq.com/openjfx/25.0.2/openjfx-25.0.2_windows-x64_bin-jmods.zip'
|
OPENJFX_JMODS_AMD64: 'https://download2.gluonhq.com/openjfx/25/openjfx-25_windows-x64_bin-jmods.zip'
|
||||||
OPENJFX_JMODS_AMD64_HASH: '33d878dfac85590c4d77c518ed413e512d34a8479d90132b230a7ddd173576b3'
|
OPENJFX_JMODS_AMD64_HASH: 'c8eb9fd039b00e0020cf6c3db8ed7876bf3ee4d27860aa697a247b83b8296ae7'
|
||||||
WINFSP_MSI: 'https://github.com/winfsp/winfsp/releases/download/v2.1/winfsp-2.1.25156.msi'
|
WINFSP_MSI: 'https://github.com/winfsp/winfsp/releases/download/v2.1/winfsp-2.1.25156.msi'
|
||||||
WINFSP_MSI_HASH: '073a70e00f77423e34bed98b86e600def93393ba5822204fac57a29324db9f7a'
|
WINFSP_MSI_HASH: '073a70e00f77423e34bed98b86e600def93393ba5822204fac57a29324db9f7a'
|
||||||
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'
|
||||||
WIX_VERSION: '6.0.2'
|
|
||||||
|
|
||||||
defaults:
|
defaults:
|
||||||
run:
|
run:
|
||||||
@@ -52,9 +51,9 @@ jobs:
|
|||||||
java-version: '25.0.1+8'
|
java-version: '25.0.1+8'
|
||||||
java-package: 'jdk'
|
java-package: 'jdk'
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||||
- name: Setup Java
|
- name: Setup Java
|
||||||
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
|
uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # v5.1.0
|
||||||
with:
|
with:
|
||||||
distribution: ${{ matrix.java-dist }}
|
distribution: ${{ matrix.java-dist }}
|
||||||
java-version: ${{ matrix.java-version }}
|
java-version: ${{ matrix.java-version }}
|
||||||
@@ -63,16 +62,14 @@ jobs:
|
|||||||
cache: 'maven'
|
cache: 'maven'
|
||||||
- name: Install wix and extensions
|
- name: Install wix and extensions
|
||||||
run: |
|
run: |
|
||||||
dotnet tool install --global wix --version ${WIX_VERSION}
|
dotnet tool install --global wix --version 6.0.0
|
||||||
wix.exe extension add --global WixToolset.UI.wixext/${WIX_VERSION}
|
wix.exe extension add WixToolset.UI.wixext/6.0.0 --global
|
||||||
wix.exe extension add --global WixToolset.Util.wixext/${WIX_VERSION}
|
wix.exe extension add WixToolset.Util.wixext/6.0.0 --global
|
||||||
env:
|
|
||||||
WIX_VERSION: ${{ env.WIX_VERSION }}
|
|
||||||
- name: Download and extract JavaFX jmods from Gluon
|
- name: Download and extract JavaFX jmods from Gluon
|
||||||
if: matrix.arch == 'x64'
|
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 --silent --fail-with-body --proto "=https" -L "${{ env.OPENJFX_JMODS_AMD64 }}" --output openjfx-jmods.zip
|
curl --output openjfx-jmods.zip -L "${{ env.OPENJFX_JMODS_AMD64 }}"
|
||||||
if(!(Get-FileHash -Path openjfx-jmods.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 }}.";
|
||||||
}
|
}
|
||||||
@@ -143,8 +140,8 @@ jobs:
|
|||||||
--java-options "-Dcryptomator.appVersion=\"${{ needs.get-version.outputs.semVerStr }}\""
|
--java-options "-Dcryptomator.appVersion=\"${{ needs.get-version.outputs.semVerStr }}\""
|
||||||
--java-options "-Dfile.encoding=\"utf-8\""
|
--java-options "-Dfile.encoding=\"utf-8\""
|
||||||
--java-options "-Djava.net.useSystemProxies=true"
|
--java-options "-Djava.net.useSystemProxies=true"
|
||||||
--java-options "-Dcryptomator.adminConfigPath=\"C:/ProgramData/Cryptomator/config.properties\""
|
|
||||||
--java-options "-Dcryptomator.logDir=\"@{localappdata}/Cryptomator\""
|
--java-options "-Dcryptomator.logDir=\"@{localappdata}/Cryptomator\""
|
||||||
|
--java-options "-Dcryptomator.pluginDir=\"@{appdata}/Cryptomator/Plugins\""
|
||||||
--java-options "-Dcryptomator.settingsPath=\"@{appdata}/Cryptomator/settings.json;@{userhome}/AppData/Roaming/Cryptomator/settings.json\""
|
--java-options "-Dcryptomator.settingsPath=\"@{appdata}/Cryptomator/settings.json;@{userhome}/AppData/Roaming/Cryptomator/settings.json\""
|
||||||
--java-options "-Dcryptomator.p12Path=\"@{appdata}/Cryptomator/key.p12;@{userhome}/AppData/Roaming/Cryptomator/key.p12\""
|
--java-options "-Dcryptomator.p12Path=\"@{appdata}/Cryptomator/key.p12;@{userhome}/AppData/Roaming/Cryptomator/key.p12\""
|
||||||
--java-options "-Dcryptomator.ipcSocketPath=\"@{localappdata}/Cryptomator/ipc.socket\""
|
--java-options "-Dcryptomator.ipcSocketPath=\"@{localappdata}/Cryptomator/ipc.socket\""
|
||||||
@@ -203,7 +200,7 @@ jobs:
|
|||||||
client-secret: ${{ secrets.AZURE_CLIENT_SECRET }}
|
client-secret: ${{ secrets.AZURE_CLIENT_SECRET }}
|
||||||
- name: Sign DLLs with Actalis CodeSigner
|
- name: Sign DLLs with Actalis CodeSigner
|
||||||
if: inputs.sign || github.event_name == 'release'
|
if: inputs.sign || github.event_name == 'release'
|
||||||
uses: skymatic/workflows/.github/actions/win-sign-action@957d3c2c08c56855fdac41e5afb9a7aca8c30dd9 # no specific version
|
uses: skymatic/workflows/.github/actions/win-sign-action@1074588008ae3326a2221ea451783280518f0366 # no specific version
|
||||||
with:
|
with:
|
||||||
base-dir: 'appdir'
|
base-dir: 'appdir'
|
||||||
file-extensions: 'dll,exe,ps1'
|
file-extensions: 'dll,exe,ps1'
|
||||||
@@ -249,11 +246,9 @@ jobs:
|
|||||||
--vendor "Skymatic GmbH"
|
--vendor "Skymatic GmbH"
|
||||||
--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}}"
|
||||||
--win-menu
|
|
||||||
--win-dir-chooser
|
--win-dir-chooser
|
||||||
--win-shortcut-prompt
|
--win-shortcut-prompt
|
||||||
--win-update-url "https:\\cryptomator.org\downloads"
|
--win-update-url "https:\\cryptomator.org\downloads"
|
||||||
--win-menu-group Cryptomator
|
|
||||||
--resource-dir dist/win/resources
|
--resource-dir dist/win/resources
|
||||||
--license-file dist/win/resources/license.rtf
|
--license-file dist/win/resources/license.rtf
|
||||||
--file-associations dist/win/resources/FAvaultFile.properties
|
--file-associations dist/win/resources/FAvaultFile.properties
|
||||||
@@ -280,7 +275,7 @@ jobs:
|
|||||||
GPG_PRIVATE_KEY: ${{ secrets.RELEASES_GPG_PRIVATE_KEY }}
|
GPG_PRIVATE_KEY: ${{ secrets.RELEASES_GPG_PRIVATE_KEY }}
|
||||||
GPG_PASSPHRASE: ${{ secrets.RELEASES_GPG_PASSPHRASE }}
|
GPG_PASSPHRASE: ${{ secrets.RELEASES_GPG_PASSPHRASE }}
|
||||||
- name: Upload artifacts
|
- name: Upload artifacts
|
||||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
|
||||||
with:
|
with:
|
||||||
name: msi-${{ matrix.arch }}
|
name: msi-${{ matrix.arch }}
|
||||||
path: |
|
path: |
|
||||||
@@ -302,23 +297,21 @@ jobs:
|
|||||||
java-version: '24.0.1+9'
|
java-version: '24.0.1+9'
|
||||||
java-package: 'jdk'
|
java-package: 'jdk'
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||||
- name: Install wix and extensions
|
- name: Install wix and extensions
|
||||||
run: |
|
run: |
|
||||||
dotnet tool install --global wix --version ${WIX_VERSION}
|
dotnet tool install --global wix --version 6.0.0
|
||||||
wix.exe extension add --global WixToolset.BootstrapperApplications.wixext/${WIX_VERSION}
|
wix.exe extension add WixToolset.BootstrapperApplications.wixext/6.0.0 --global
|
||||||
wix.exe extension add --global WixToolset.Util.wixext/${WIX_VERSION}
|
wix.exe extension add WixToolset.Util.wixext/6.0.0 --global
|
||||||
env:
|
|
||||||
WIX_VERSION: ${{ env.WIX_VERSION }}
|
|
||||||
- name: Download .msi
|
- name: Download .msi
|
||||||
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
|
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
|
||||||
with:
|
with:
|
||||||
name: msi-${{ matrix.arch }}
|
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
|
||||||
- name: Setup Java
|
- name: Setup Java
|
||||||
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
|
uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # v5.1.0
|
||||||
with:
|
with:
|
||||||
distribution: ${{ matrix.java-dist }}
|
distribution: ${{ matrix.java-dist }}
|
||||||
java-version: ${{ matrix.java-version }}
|
java-version: ${{ matrix.java-version }}
|
||||||
@@ -338,7 +331,7 @@ jobs:
|
|||||||
shell: pwsh
|
shell: pwsh
|
||||||
- name: Download WinFsp
|
- name: Download WinFsp
|
||||||
run: |
|
run: |
|
||||||
curl --silent --fail-with-body --proto "=https" -L ${{ env.WINFSP_MSI }} --output $env:WINFSP_PATH
|
curl --output $env:WINFSP_PATH -L ${{ env.WINFSP_MSI }}
|
||||||
$computedHash = (Get-FileHash -Path $env:WINFSP_PATH -Algorithm SHA256).Hash.ToLower()
|
$computedHash = (Get-FileHash -Path $env:WINFSP_PATH -Algorithm SHA256).Hash.ToLower()
|
||||||
if ($computedHash -ne "${{ env.WINFSP_MSI_HASH }}") {
|
if ($computedHash -ne "${{ env.WINFSP_MSI_HASH }}") {
|
||||||
throw "Checksum mismatch for $env:WINFSP_PATH (expected ${{ env.WINFSP_MSI_HASH }}, got $computedHash)."
|
throw "Checksum mismatch for $env:WINFSP_PATH (expected ${{ env.WINFSP_MSI_HASH }}, got $computedHash)."
|
||||||
@@ -348,7 +341,7 @@ jobs:
|
|||||||
shell: pwsh
|
shell: pwsh
|
||||||
- name: Download Legacy-WinFsp uninstaller
|
- name: Download Legacy-WinFsp uninstaller
|
||||||
run: |
|
run: |
|
||||||
curl --silent --fail-with-body --proto "=https" -L ${{ env.WINFSP_UNINSTALLER }} --output dist/win/bundle/resources/winfsp-uninstaller.exe
|
curl --output dist/win/bundle/resources/winfsp-uninstaller.exe -L ${{ env.WINFSP_UNINSTALLER }}
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
- name: Create Wix Burn bundle
|
- name: Create Wix Burn bundle
|
||||||
working-directory: dist/win
|
working-directory: dist/win
|
||||||
@@ -381,7 +374,7 @@ jobs:
|
|||||||
client-secret: ${{ secrets.AZURE_CLIENT_SECRET }}
|
client-secret: ${{ secrets.AZURE_CLIENT_SECRET }}
|
||||||
- name: Sign burn engine with Actalis CodeSigner
|
- name: Sign burn engine with Actalis CodeSigner
|
||||||
if: inputs.sign || github.event_name == 'release'
|
if: inputs.sign || github.event_name == 'release'
|
||||||
uses: skymatic/workflows/.github/actions/win-sign-action@957d3c2c08c56855fdac41e5afb9a7aca8c30dd9 # no specific version
|
uses: skymatic/workflows/.github/actions/win-sign-action@1074588008ae3326a2221ea451783280518f0366 # no specific version
|
||||||
with:
|
with:
|
||||||
base-dir: 'tmp'
|
base-dir: 'tmp'
|
||||||
file-extensions: 'exe'
|
file-extensions: 'exe'
|
||||||
@@ -405,7 +398,7 @@ jobs:
|
|||||||
client-secret: ${{ secrets.AZURE_CLIENT_SECRET }}
|
client-secret: ${{ secrets.AZURE_CLIENT_SECRET }}
|
||||||
- name: Sign installer with Actalis CodeSigner
|
- name: Sign installer with Actalis CodeSigner
|
||||||
if: inputs.sign || github.event_name == 'release'
|
if: inputs.sign || github.event_name == 'release'
|
||||||
uses: skymatic/workflows/.github/actions/win-sign-action@957d3c2c08c56855fdac41e5afb9a7aca8c30dd9 # no specific version
|
uses: skymatic/workflows/.github/actions/win-sign-action@1074588008ae3326a2221ea451783280518f0366 # no specific version
|
||||||
with:
|
with:
|
||||||
base-dir: 'installer'
|
base-dir: 'installer'
|
||||||
file-extensions: 'exe'
|
file-extensions: 'exe'
|
||||||
@@ -423,7 +416,7 @@ jobs:
|
|||||||
GPG_PRIVATE_KEY: ${{ secrets.RELEASES_GPG_PRIVATE_KEY }}
|
GPG_PRIVATE_KEY: ${{ secrets.RELEASES_GPG_PRIVATE_KEY }}
|
||||||
GPG_PASSPHRASE: ${{ secrets.RELEASES_GPG_PASSPHRASE }}
|
GPG_PASSPHRASE: ${{ secrets.RELEASES_GPG_PASSPHRASE }}
|
||||||
- name: Upload artifacts
|
- name: Upload artifacts
|
||||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
|
||||||
with:
|
with:
|
||||||
name: exe-${{ matrix.executable-suffix }}
|
name: exe-${{ matrix.executable-suffix }}
|
||||||
path: |
|
path: |
|
||||||
@@ -441,7 +434,7 @@ jobs:
|
|||||||
download-url-exe-x64: ${{ fromJSON(steps.publish.outputs.assets)[2].browser_download_url }}
|
download-url-exe-x64: ${{ fromJSON(steps.publish.outputs.assets)[2].browser_download_url }}
|
||||||
steps:
|
steps:
|
||||||
- name: Download installers
|
- name: Download installers
|
||||||
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
|
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
|
||||||
with:
|
with:
|
||||||
merge-multiple: true
|
merge-multiple: true
|
||||||
- name: Publish installers on GitHub Releases
|
- name: Publish installers on GitHub Releases
|
||||||
|
|||||||
Generated
+10
-33
@@ -12,15 +12,17 @@
|
|||||||
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
|
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
|
||||||
<outputRelativeToContentRoot value="true" />
|
<outputRelativeToContentRoot value="true" />
|
||||||
<option name="dagger.fastInit" value="enabled" />
|
<option name="dagger.fastInit" value="enabled" />
|
||||||
|
<option name="dagger.formatGeneratedSource" value="enabled" />
|
||||||
<processorPath useClasspath="false">
|
<processorPath useClasspath="false">
|
||||||
<entry name="$MAVEN_REPOSITORY$/com/google/dagger/dagger-compiler/2.59.1/dagger-compiler-2.59.1.jar" />
|
<entry name="$MAVEN_REPOSITORY$/com/google/dagger/dagger-compiler/2.57.2/dagger-compiler-2.57.2.jar" />
|
||||||
<entry name="$MAVEN_REPOSITORY$/com/google/dagger/dagger/2.59.1/dagger-2.59.1.jar" />
|
<entry name="$MAVEN_REPOSITORY$/com/google/dagger/dagger/2.57.2/dagger-2.57.2.jar" />
|
||||||
<entry name="$MAVEN_REPOSITORY$/jakarta/inject/jakarta.inject-api/2.0.1/jakarta.inject-api-2.0.1.jar" />
|
<entry name="$MAVEN_REPOSITORY$/jakarta/inject/jakarta.inject-api/2.0.1/jakarta.inject-api-2.0.1.jar" />
|
||||||
<entry name="$MAVEN_REPOSITORY$/org/jspecify/jspecify/1.0.0/jspecify-1.0.0.jar" />
|
<entry name="$MAVEN_REPOSITORY$/org/jspecify/jspecify/1.0.0/jspecify-1.0.0.jar" />
|
||||||
<entry name="$MAVEN_REPOSITORY$/com/google/dagger/dagger-spi/2.59.1/dagger-spi-2.59.1.jar" />
|
<entry name="$MAVEN_REPOSITORY$/com/google/dagger/dagger-spi/2.57.2/dagger-spi-2.57.2.jar" />
|
||||||
<entry name="$MAVEN_REPOSITORY$/com/google/code/findbugs/jsr305/3.0.2/jsr305-3.0.2.jar" />
|
<entry name="$MAVEN_REPOSITORY$/com/google/code/findbugs/jsr305/3.0.2/jsr305-3.0.2.jar" />
|
||||||
<entry name="$MAVEN_REPOSITORY$/com/google/devtools/ksp/symbol-processing-api/2.2.20-2.0.3/symbol-processing-api-2.2.20-2.0.3.jar" />
|
<entry name="$MAVEN_REPOSITORY$/com/google/devtools/ksp/symbol-processing-api/2.1.21-2.0.2/symbol-processing-api-2.1.21-2.0.2.jar" />
|
||||||
<entry name="$MAVEN_REPOSITORY$/com/google/googlejavaformat/google-java-format/1.33.0/google-java-format-1.33.0.jar" />
|
<entry name="$MAVEN_REPOSITORY$/com/google/googlejavaformat/google-java-format/1.5/google-java-format-1.5.jar" />
|
||||||
|
<entry name="$MAVEN_REPOSITORY$/com/google/errorprone/javac-shaded/9-dev-r4023-3/javac-shaded-9-dev-r4023-3.jar" />
|
||||||
<entry name="$MAVEN_REPOSITORY$/com/google/guava/failureaccess/1.0.2/failureaccess-1.0.2.jar" />
|
<entry name="$MAVEN_REPOSITORY$/com/google/guava/failureaccess/1.0.2/failureaccess-1.0.2.jar" />
|
||||||
<entry name="$MAVEN_REPOSITORY$/com/google/guava/guava/33.0.0-jre/guava-33.0.0-jre.jar" />
|
<entry name="$MAVEN_REPOSITORY$/com/google/guava/guava/33.0.0-jre/guava-33.0.0-jre.jar" />
|
||||||
<entry name="$MAVEN_REPOSITORY$/com/google/guava/listenablefuture/9999.0-empty-to-avoid-conflict-with-guava/listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar" />
|
<entry name="$MAVEN_REPOSITORY$/com/google/guava/listenablefuture/9999.0-empty-to-avoid-conflict-with-guava/listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar" />
|
||||||
@@ -35,33 +37,8 @@
|
|||||||
<entry name="$MAVEN_REPOSITORY$/javax/inject/javax.inject/1/javax.inject-1.jar" />
|
<entry name="$MAVEN_REPOSITORY$/javax/inject/javax.inject/1/javax.inject-1.jar" />
|
||||||
<entry name="$MAVEN_REPOSITORY$/net/ltgt/gradle/incap/incap/0.2/incap-0.2.jar" />
|
<entry name="$MAVEN_REPOSITORY$/net/ltgt/gradle/incap/incap/0.2/incap-0.2.jar" />
|
||||||
<entry name="$MAVEN_REPOSITORY$/org/checkerframework/checker-compat-qual/2.5.3/checker-compat-qual-2.5.3.jar" />
|
<entry name="$MAVEN_REPOSITORY$/org/checkerframework/checker-compat-qual/2.5.3/checker-compat-qual-2.5.3.jar" />
|
||||||
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-metadata-jvm/2.2.20/kotlin-metadata-jvm-2.2.20.jar" />
|
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-metadata-jvm/2.1.21/kotlin-metadata-jvm-2.1.21.jar" />
|
||||||
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib/2.2.20/kotlin-stdlib-2.2.20.jar" />
|
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib/2.1.21/kotlin-stdlib-2.1.21.jar" />
|
||||||
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/annotations/13.0/annotations-13.0.jar" />
|
|
||||||
<entry name="$MAVEN_REPOSITORY$/com/google/dagger/dagger-compiler/2.59.1/dagger-compiler-2.59.1.jar" />
|
|
||||||
<entry name="$MAVEN_REPOSITORY$/com/google/dagger/dagger/2.59.1/dagger-2.59.1.jar" />
|
|
||||||
<entry name="$MAVEN_REPOSITORY$/jakarta/inject/jakarta.inject-api/2.0.1/jakarta.inject-api-2.0.1.jar" />
|
|
||||||
<entry name="$MAVEN_REPOSITORY$/org/jspecify/jspecify/1.0.0/jspecify-1.0.0.jar" />
|
|
||||||
<entry name="$MAVEN_REPOSITORY$/com/google/dagger/dagger-spi/2.59.1/dagger-spi-2.59.1.jar" />
|
|
||||||
<entry name="$MAVEN_REPOSITORY$/com/google/code/findbugs/jsr305/3.0.2/jsr305-3.0.2.jar" />
|
|
||||||
<entry name="$MAVEN_REPOSITORY$/com/google/devtools/ksp/symbol-processing-api/2.2.20-2.0.3/symbol-processing-api-2.2.20-2.0.3.jar" />
|
|
||||||
<entry name="$MAVEN_REPOSITORY$/com/google/googlejavaformat/google-java-format/1.33.0/google-java-format-1.33.0.jar" />
|
|
||||||
<entry name="$MAVEN_REPOSITORY$/com/google/guava/failureaccess/1.0.2/failureaccess-1.0.2.jar" />
|
|
||||||
<entry name="$MAVEN_REPOSITORY$/com/google/guava/guava/33.0.0-jre/guava-33.0.0-jre.jar" />
|
|
||||||
<entry name="$MAVEN_REPOSITORY$/com/google/guava/listenablefuture/9999.0-empty-to-avoid-conflict-with-guava/listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar" />
|
|
||||||
<entry name="$MAVEN_REPOSITORY$/org/checkerframework/checker-qual/3.41.0/checker-qual-3.41.0.jar" />
|
|
||||||
<entry name="$MAVEN_REPOSITORY$/com/google/errorprone/error_prone_annotations/2.23.0/error_prone_annotations-2.23.0.jar" />
|
|
||||||
<entry name="$MAVEN_REPOSITORY$/com/google/j2objc/j2objc-annotations/2.8/j2objc-annotations-2.8.jar" />
|
|
||||||
<entry name="$MAVEN_REPOSITORY$/com/squareup/javapoet/1.13.0/javapoet-1.13.0.jar" />
|
|
||||||
<entry name="$MAVEN_REPOSITORY$/com/squareup/kotlinpoet/1.11.0/kotlinpoet-1.11.0.jar" />
|
|
||||||
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.6.10/kotlin-stdlib-jdk8-1.6.10.jar" />
|
|
||||||
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.6.10/kotlin-stdlib-jdk7-1.6.10.jar" />
|
|
||||||
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-reflect/1.6.10/kotlin-reflect-1.6.10.jar" />
|
|
||||||
<entry name="$MAVEN_REPOSITORY$/javax/inject/javax.inject/1/javax.inject-1.jar" />
|
|
||||||
<entry name="$MAVEN_REPOSITORY$/net/ltgt/gradle/incap/incap/0.2/incap-0.2.jar" />
|
|
||||||
<entry name="$MAVEN_REPOSITORY$/org/checkerframework/checker-compat-qual/2.5.3/checker-compat-qual-2.5.3.jar" />
|
|
||||||
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-metadata-jvm/2.2.20/kotlin-metadata-jvm-2.2.20.jar" />
|
|
||||||
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib/2.2.20/kotlin-stdlib-2.2.20.jar" />
|
|
||||||
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/annotations/13.0/annotations-13.0.jar" />
|
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/annotations/13.0/annotations-13.0.jar" />
|
||||||
</processorPath>
|
</processorPath>
|
||||||
<module name="cryptomator" />
|
<module name="cryptomator" />
|
||||||
@@ -70,7 +47,7 @@
|
|||||||
</component>
|
</component>
|
||||||
<component name="JavacSettings">
|
<component name="JavacSettings">
|
||||||
<option name="ADDITIONAL_OPTIONS_OVERRIDE">
|
<option name="ADDITIONAL_OPTIONS_OVERRIDE">
|
||||||
<module name="cryptomator" options="-Adagger.fastInit=enabled" />
|
<module name="cryptomator" options="-Adagger.fastInit=enabled -Adagger.formatGeneratedSource=enabled" />
|
||||||
</option>
|
</option>
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
+8
-36
@@ -7,46 +7,18 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|||||||
The changelog starts with version 1.19.0.
|
The changelog starts with version 1.19.0.
|
||||||
Changes to prior versions can be found on the [Github release page](https://github.com/cryptomator/cryptomator/releases).
|
Changes to prior versions can be found on the [Github release page](https://github.com/cryptomator/cryptomator/releases).
|
||||||
|
|
||||||
## [1.19.0](https://github.com/cryptomator/cryptomator/releases/tag/1.19.0) - 2026-03-09
|
## [Unreleased](https://github.com/cryptomator/cryptomator/compare/1.18.0...HEAD)
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
* Self-Update Mechanism ([#3948](https://github.com/cryptomator/cryptomator/pull/3948))
|
* Self-Update Mechanism (#3948)
|
||||||
* Implemented `.dmg` update mechanism
|
* Implemented `.dmg` update mechanism
|
||||||
* Implemented Flatpak update mechanism
|
* Implemented Flatpak update mechanism
|
||||||
* App notifications ([#4069](https://github.com/cryptomator/cryptomator/pull/4069))
|
* App notifications (#4069)
|
||||||
* Mark files in-use for Hub vaults ([#4078](https://github.com/cryptomator/cryptomator/pull/4078))
|
* Mark files in-use for Hub vaults (#4078)
|
||||||
* Accessibility: Adjust app to be used with a screen reader ([#547](https://github.com/cryptomator/cryptomator/issues/547))
|
|
||||||
* Show Archived Vault Dialog on unlock when Hub returns 410 ([#4081](https://github.com/cryptomator/cryptomator/pull/4081))
|
|
||||||
* Support automatic app theme selection according to OS theme on Linux ([#4027](https://github.com/cryptomator/cryptomator/issues/4027))
|
|
||||||
* Admin configuration: Allow overwriting certain app properties by external config file ([#4105](https://github.com/cryptomator/cryptomator/pull/4105))
|
|
||||||
* New keychain backend using [secret service API](https://specifications.freedesktop.org/secret-service/0.2) for Linux ([#4025](https://github.com/cryptomator/cryptomator/pull/4025))
|
|
||||||
* Liquid Glass icon for macOS ([#4166](https://github.com/cryptomator/cryptomator/pull/4166))
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
* Fixed password reset/show recovery possible for vaults without masterkey file ([#4120](https://github.com/cryptomator/cryptomator/pull/4120))
|
|
||||||
* Fixed restore vault config failed due to selecting a directory instead of file ([#4141](https://github.com/cryptomator/cryptomator/issues/4141))
|
|
||||||
* Fixed leaking of cleartext paths into application log ([GHSA-j83j-mwhc-rcgw](https://github.com/cryptomator/cryptomator/security/advisories/GHSA-j83j-mwhc-rcgw))
|
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
* Disable user defined app start config on Windows ([#4132](https://github.com/cryptomator/cryptomator/issues/4132))
|
* Built using JDK 25 (#4031)
|
||||||
* Disable plugin loading by default ([#4136](https://github.com/cryptomator/cryptomator/4136))
|
* Modernized Templage for GitHub Releases
|
||||||
* Use JDK 25 ([#4031](https://github.com/cryptomator/cryptomator/pull/4031))
|
|
||||||
* Update JavaFX to 25.0.2 ([#4145](https://github.com/cryptomator/cryptomator/pull/4145))
|
|
||||||
* Updated translations
|
|
||||||
* Updated dependencies
|
|
||||||
* `ch.qos.logback:*` from 1.5.19 to 1.5.32
|
|
||||||
* `com.fasterxml.jackson.core:jackson-databind` from 2.20.0 to 2.21.1
|
|
||||||
* `com.fasterxml.jackson.datatype:jackson-datatype-jsr310` from 2.20.0 to 2.21.1
|
|
||||||
* `com.github.ben-manes.caffeine:caffeine` from 3.2.2 to 3.2.3
|
|
||||||
* `com.google.dagger:*` from 2.57.2 to 2.59.2
|
|
||||||
* `org.apache.commons:commons-lang3` from 3.19.0 to 3.20.0
|
|
||||||
* `org.cryptomator:cryptofs` from 2.9.0 to 2.10.0
|
|
||||||
* `org.cryptomator:cryptolib` from 2.2.1 to 2.2.2
|
|
||||||
* `org.cryptomator:fuse-nio-adapter` from 5.1.0 to 6.0.1
|
|
||||||
* `org.cryptomator:integrations-api` from 1.7.0 to 1.8.0-beta1
|
|
||||||
* `org.cryptomator:integrations-linux` from 1.6.1 to 1.7.0-beta4
|
|
||||||
* `org.cryptomator:integrations-mac` from 1.4.1 to 1.5.0-beta3
|
|
||||||
* `org.cryptomator:integrations-win` from 1.5.1 to 1.6.0
|
|
||||||
* `org.cryptomator:webdav-nio-adapter` from 3.0.0 to 3.0.1
|
|
||||||
* `org.cryptomator:webdav-nio-adapter-servlet` to 1.2.12
|
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
* Windows: Removed debug launcher start menu entry ([#4089](https://github.com/cryptomator/cryptomator/issues/4089))
|
||||||
@@ -78,7 +78,7 @@ For more information on the security details visit [cryptomator.org](https://doc
|
|||||||
|
|
||||||
### Dependencies
|
### Dependencies
|
||||||
|
|
||||||
* JDK 25 (e.g. temurin, zulu)
|
* JDK 24 (e.g. temurin, zulu)
|
||||||
* Maven 3
|
* Maven 3
|
||||||
|
|
||||||
### Run Maven
|
### Run Maven
|
||||||
|
|||||||
Vendored
-8
@@ -1,8 +0,0 @@
|
|||||||
# This is the Cryptomator administrative configuration file.
|
|
||||||
# It is a simple key-value pair file.
|
|
||||||
# Lines starting with '#' are comments and will be ignored.
|
|
||||||
# For more info, read the docs at https://docs.cryptomator.org/desktop/advanced-settings/
|
|
||||||
#
|
|
||||||
# Example:
|
|
||||||
# Sets the plugin directory and enables plugin loading
|
|
||||||
# cryptomator.pluginDir=@{userhome}/Cryptomator/Plugins
|
|
||||||
Vendored
+4
-4
@@ -23,12 +23,12 @@ mvn -B -f ../../../pom.xml clean package -Plinux -DskipTests
|
|||||||
cp ../../../LICENSE.txt ../../../target
|
cp ../../../LICENSE.txt ../../../target
|
||||||
cp ../../../target/cryptomator-*.jar ../../../target/mods
|
cp ../../../target/cryptomator-*.jar ../../../target/mods
|
||||||
|
|
||||||
JAVAFX_VERSION=25.0.2
|
JAVAFX_VERSION=25
|
||||||
JAVAFX_ARCH="x64"
|
JAVAFX_ARCH="x64"
|
||||||
JAVAFX_JMODS_SHA256='e0a9c29d8cf3af9b8b48848b43f87b5785bc107c53a951b19668ce05842bba1b'
|
JAVAFX_JMODS_SHA256='96e520f48610d8ffb94ca30face1f11ffe8a977ddc1c4ff80b1a9e9f048bd94e'
|
||||||
if [ "${CPU_ARCH}" = "aarch64" ]; then
|
if [ "${CPU_ARCH}" = "aarch64" ]; then
|
||||||
JAVAFX_ARCH="aarch64"
|
JAVAFX_ARCH="aarch64"
|
||||||
JAVAFX_JMODS_SHA256='c3408f818693cce09e59829a8e862a82c7695fdfcd585c41cfd527f5fc3fe646'
|
JAVAFX_JMODS_SHA256='951c52481af0ec5885b06f1ebaa8a10da7e8ea23c5e1ef3e2f6f11fa1b3a7ce1'
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# download javaFX jmods
|
# download javaFX jmods
|
||||||
@@ -88,8 +88,8 @@ ${JAVA_HOME}/bin/jpackage \
|
|||||||
--app-version "${VERSION}.${REVISION_NO}" \
|
--app-version "${VERSION}.${REVISION_NO}" \
|
||||||
--java-options "-Dfile.encoding=\"utf-8\"" \
|
--java-options "-Dfile.encoding=\"utf-8\"" \
|
||||||
--java-options "-Djava.net.useSystemProxies=true" \
|
--java-options "-Djava.net.useSystemProxies=true" \
|
||||||
--java-options "-Dcryptomator.adminConfigPath=\"/etc/cryptomator/config.properties\"" \
|
|
||||||
--java-options "-Dcryptomator.logDir=\"@{userhome}/.local/share/Cryptomator/logs\"" \
|
--java-options "-Dcryptomator.logDir=\"@{userhome}/.local/share/Cryptomator/logs\"" \
|
||||||
|
--java-options "-Dcryptomator.pluginDir=\"@{userhome}/.local/share/Cryptomator/plugins\"" \
|
||||||
--java-options "-Dcryptomator.settingsPath=\"@{userhome}/.config/Cryptomator/settings.json:@{userhome}/.Cryptomator/settings.json\"" \
|
--java-options "-Dcryptomator.settingsPath=\"@{userhome}/.config/Cryptomator/settings.json:@{userhome}/.Cryptomator/settings.json\"" \
|
||||||
--java-options "-Dcryptomator.p12Path=\"@{userhome}/.config/Cryptomator/key.p12\"" \
|
--java-options "-Dcryptomator.p12Path=\"@{userhome}/.config/Cryptomator/key.p12\"" \
|
||||||
--java-options "-Dcryptomator.ipcSocketPath=\"@{userhome}/.config/Cryptomator/ipc.socket\"" \
|
--java-options "-Dcryptomator.ipcSocketPath=\"@{userhome}/.config/Cryptomator/ipc.socket\"" \
|
||||||
|
|||||||
@@ -83,9 +83,6 @@
|
|||||||
</content_rating>
|
</content_rating>
|
||||||
|
|
||||||
<releases>
|
<releases>
|
||||||
<release date="2026-03-09" version="1.19.0">
|
|
||||||
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.19.0</url>
|
|
||||||
</release>
|
|
||||||
<release date="2025-11-12" version="1.18.0">
|
<release date="2025-11-12" version="1.18.0">
|
||||||
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.18.0</url>
|
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.18.0</url>
|
||||||
</release>
|
</release>
|
||||||
|
|||||||
Vendored
+1
-1
@@ -51,8 +51,8 @@ override_dh_auto_build:
|
|||||||
--java-options "-Xmx256m" \
|
--java-options "-Xmx256m" \
|
||||||
--java-options "-Dfile.encoding=\"utf-8\"" \
|
--java-options "-Dfile.encoding=\"utf-8\"" \
|
||||||
--java-options "-Djava.net.useSystemProxies=true" \
|
--java-options "-Djava.net.useSystemProxies=true" \
|
||||||
--java-options "-Dcryptomator.adminConfigPath=\"/etc/cryptomator/config.properties\"" \
|
|
||||||
--java-options "-Dcryptomator.logDir=\"@{userhome}/.local/share/Cryptomator/logs\"" \
|
--java-options "-Dcryptomator.logDir=\"@{userhome}/.local/share/Cryptomator/logs\"" \
|
||||||
|
--java-options "-Dcryptomator.pluginDir=\"@{userhome}/.local/share/Cryptomator/plugins\"" \
|
||||||
--java-options "-Dcryptomator.settingsPath=\"@{userhome}/.config/Cryptomator/settings.json:@{userhome}/.Cryptomator/settings.json\"" \
|
--java-options "-Dcryptomator.settingsPath=\"@{userhome}/.config/Cryptomator/settings.json:@{userhome}/.Cryptomator/settings.json\"" \
|
||||||
--java-options "-Dcryptomator.p12Path=\"@{userhome}/.config/Cryptomator/key.p12\"" \
|
--java-options "-Dcryptomator.p12Path=\"@{userhome}/.config/Cryptomator/key.p12\"" \
|
||||||
--java-options "-Dcryptomator.ipcSocketPath=\"@{userhome}/.config/Cryptomator/ipc.socket\"" \
|
--java-options "-Dcryptomator.ipcSocketPath=\"@{userhome}/.config/Cryptomator/ipc.socket\"" \
|
||||||
|
|||||||
Vendored
-118
@@ -1,118 +0,0 @@
|
|||||||
# Maintainer: Aaron Graves <linux@ajgraves.com>
|
|
||||||
# Contributor: Julian Raufelder <arch@raufelder.com>
|
|
||||||
# Contributor: Morten Linderud <morten@linderud.pw>
|
|
||||||
# Contributor: Sebastian Stenzel <sebastian.stenzel@gmail.com>
|
|
||||||
# Contributor: Armin Schrenk <armin.schrenk@skymatic.de>
|
|
||||||
|
|
||||||
pkgname=cryptomator
|
|
||||||
pkgver=$PKG_VERSION
|
|
||||||
pkgrel=$PKG_RELEASE
|
|
||||||
pkgdesc="Multiplatform transparent client-side encryption of your files in the cloud."
|
|
||||||
arch=('any')
|
|
||||||
url="https://cryptomator.org/"
|
|
||||||
license=('GPL3')
|
|
||||||
depends=('fuse3' 'alsa-lib' 'hicolor-icon-theme' 'libxtst' 'libnet' 'libxrender')
|
|
||||||
makedepends=('maven' 'unzip')
|
|
||||||
optdepends=('keepassxc-cryptomator: Use KeePassXC to store vault passwords' 'ttf-hanazono: Install this font when using Japanese system language')
|
|
||||||
_jdkver=25.0.2+10
|
|
||||||
_jfxver=25.0.2
|
|
||||||
_src_app_dir=cryptomator-${pkgver//_/-}
|
|
||||||
source=($SOURCES);
|
|
||||||
source_x86_64=("jdk-${_jdkver}.tar.gz::https://github.com/adoptium/temurin${_jdkver:0:2}-binaries/releases/download/jdk-${_jdkver//\+/%2B}/OpenJDK${_jdkver:0:2}U-jdk_x64_linux_hotspot_${_jdkver//\+/_}.tar.gz"
|
|
||||||
"openjfx-${_jfxver}.zip::https://download2.gluonhq.com/openjfx/${_jfxver}/openjfx-${_jfxver}_linux-x64_bin-jmods.zip")
|
|
||||||
source_aarch64=("jdk-${_jdkver}.tar.gz::https://github.com/adoptium/temurin${_jdkver:0:2}-binaries/releases/download/jdk-${_jdkver//\+/%2B}/OpenJDK${_jdkver:0:2}U-jdk_aarch64_linux_hotspot_${_jdkver//\+/_}.tar.gz"
|
|
||||||
"openjfx-${_jfxver}.zip::https://download2.gluonhq.com/openjfx/${_jfxver}/openjfx-${_jfxver}_linux-aarch64_bin-jmods.zip")
|
|
||||||
noextract=("jdk-${_jdkver}.tar.gz" "openjfx-${_jfxver}.zip")
|
|
||||||
sha256sums=($SOURCES_SHA)
|
|
||||||
sha256sums_x86_64=('987387933b64b9833846dee373b640440d3e1fd48a04804ec01a6dbf718e8ab8'
|
|
||||||
'e0a9c29d8cf3af9b8b48848b43f87b5785bc107c53a951b19668ce05842bba1b')
|
|
||||||
sha256sums_aarch64=('a9d73e711d967dc44896d4f430f73a68fd33590dabc29a7f2fb9f593425b854c'
|
|
||||||
'c3408f818693cce09e59829a8e862a82c7695fdfcd585c41cfd527f5fc3fe646')
|
|
||||||
options=('!strip')
|
|
||||||
|
|
||||||
validpgpkeys=('58117AFA1F85B3EEC154677D615D449FE6E6A235')
|
|
||||||
|
|
||||||
build() {
|
|
||||||
export JAVA_HOME="${srcdir}/jdk-${_jdkver}"
|
|
||||||
JMODS_PATH="${srcdir}/openjfx-${_jfxver}-jmods"
|
|
||||||
#JEP 493
|
|
||||||
if ! $(${JAVA_HOME}/bin/jlink --help | grep -q "Linking from run-time image enabled"); then
|
|
||||||
JMODS_PATH="${JMODS_PATH}:${JAVA_HOME}/jmods:"
|
|
||||||
fi
|
|
||||||
|
|
||||||
tar xfz "jdk-${_jdkver}.tar.gz"
|
|
||||||
|
|
||||||
mkdir "openjfx-${_jfxver}-jmods"
|
|
||||||
unzip -j "openjfx-${_jfxver}.zip" \*/javafx.base.jmod \*/javafx.controls.jmod \*/javafx.fxml.jmod \*/javafx.graphics.jmod -d "openjfx-${_jfxver}-jmods"
|
|
||||||
|
|
||||||
cd "${srcdir}/${_src_app_dir}"
|
|
||||||
|
|
||||||
mvn -B clean package -DskipTests -Plinux
|
|
||||||
|
|
||||||
cp LICENSE.txt target
|
|
||||||
cp target/cryptomator-*.jar target/mods
|
|
||||||
|
|
||||||
cd target
|
|
||||||
|
|
||||||
"$JAVA_HOME/bin/jlink" \
|
|
||||||
--output runtime \
|
|
||||||
--module-path "$JMODS_PATH" \
|
|
||||||
--add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,javafx.base,javafx.graphics,javafx.controls,javafx.fxml,jdk.crypto.ec,jdk.crypto.cryptoki,jdk.unsupported,jdk.security.auth,jdk.accessibility,jdk.management.jfr,jdk.net,java.compiler \
|
|
||||||
--strip-native-commands \
|
|
||||||
--no-header-files \
|
|
||||||
--no-man-pages \
|
|
||||||
--strip-debug \
|
|
||||||
--compress=zip-0
|
|
||||||
|
|
||||||
##Note: jpackage does not allow -beta suffixes, have to strip those
|
|
||||||
"$JAVA_HOME/bin/jpackage" \
|
|
||||||
--type app-image \
|
|
||||||
--runtime-image runtime \
|
|
||||||
--input libs \
|
|
||||||
--module-path mods \
|
|
||||||
--module org.cryptomator.desktop/org.cryptomator.launcher.Cryptomator \
|
|
||||||
--dest . \
|
|
||||||
--name cryptomator \
|
|
||||||
--vendor "Skymatic GmbH" \
|
|
||||||
--copyright "(C) 2016 - 2026 Skymatic GmbH" \
|
|
||||||
--java-options "--enable-preview" \
|
|
||||||
--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 "-Xmx256m" \
|
|
||||||
--java-options "-Dfile.encoding=\"utf-8\"" \
|
|
||||||
--java-options "-Djava.net.useSystemProxies=true" \
|
|
||||||
--java-options "-Dcryptomator.adminConfigPath=\"/etc/cryptomator/config.properties\"" \
|
|
||||||
--java-options "-Dcryptomator.appVersion=\"${pkgver//_/-}\"" \
|
|
||||||
--java-options "-Dcryptomator.buildNumber=\"aur-${pkgrel}\"" \
|
|
||||||
--java-options "-Dcryptomator.disableUpdateCheck=true" \
|
|
||||||
--java-options "-Dcryptomator.integrationsLinux.autoStartCmd=\"cryptomator\"" \
|
|
||||||
--java-options "-Dcryptomator.ipcSocketPath=\"@{userhome}/.config/Cryptomator/ipc.socket\"" \
|
|
||||||
--java-options "-Dcryptomator.logDir=\"@{userhome}/.local/share/Cryptomator/logs\"" \
|
|
||||||
--java-options "-Dcryptomator.mountPointsDir=\"@{userhome}/.local/share/Cryptomator/mnt\"" \
|
|
||||||
--java-options "-Dcryptomator.networking.truststore.p12Path=\"/etc/cryptomator/certs.p12\"" \
|
|
||||||
--java-options "-Dcryptomator.pluginDir=\"@{userhome}/.local/share/Cryptomator/plugins\"" \
|
|
||||||
--java-options "-Dcryptomator.p12Path=\"@{userhome}/.config/Cryptomator/key.p12\"" \
|
|
||||||
--java-options "-Dcryptomator.settingsPath=\"@{userhome}/.config/Cryptomator/settings.json:~/.Cryptomator/settings.json\"" \
|
|
||||||
--java-options "-Dcryptomator.showTrayIcon=true" \
|
|
||||||
--app-version "${pkgver//_*/}" \
|
|
||||||
--verbose
|
|
||||||
}
|
|
||||||
|
|
||||||
package() {
|
|
||||||
install -Dm644 "${srcdir}/${_src_app_dir}/dist/linux/common/application-vnd.cryptomator.vault.xml" "${pkgdir}/usr/share/mime/packages/cryptomator-vault.xml"
|
|
||||||
install -Dm644 "${srcdir}/${_src_app_dir}/dist/linux/common/org.cryptomator.Cryptomator.desktop" "${pkgdir}/usr/share/applications/org.cryptomator.Cryptomator.desktop"
|
|
||||||
install -Dm644 "${srcdir}/${_src_app_dir}/dist/linux/common/org.cryptomator.Cryptomator256.png" "${pkgdir}/usr/share/icons/hicolor/256x256/apps/org.cryptomator.Cryptomator.png"
|
|
||||||
install -Dm644 "${srcdir}/${_src_app_dir}/dist/linux/common/org.cryptomator.Cryptomator512.png" "${pkgdir}/usr/share/icons/hicolor/512x512/apps/org.cryptomator.Cryptomator.png"
|
|
||||||
install -Dm644 "${srcdir}/${_src_app_dir}/dist/linux/common/org.cryptomator.Cryptomator.svg" "${pkgdir}/usr/share/icons/hicolor/scalable/apps/org.cryptomator.Cryptomator.svg"
|
|
||||||
install -Dm644 "${srcdir}/${_src_app_dir}/dist/linux/common/org.cryptomator.Cryptomator.tray.svg" "${pkgdir}/usr/share/icons/hicolor/scalable/apps/org.cryptomator.Cryptomator.tray.svg"
|
|
||||||
install -Dm644 "${srcdir}/${_src_app_dir}/dist/linux/common/org.cryptomator.Cryptomator.tray-unlocked.svg" "${pkgdir}/usr/share/icons/hicolor/scalable/apps/org.cryptomator.Cryptomator.tray-unlocked.svg"
|
|
||||||
install -Dm644 "${srcdir}/${_src_app_dir}/dist/linux/common/org.cryptomator.Cryptomator.tray.svg" "${pkgdir}/usr/share/icons/hicolor/symbolic/apps/org.cryptomator.Cryptomator.tray-symbolic.svg"
|
|
||||||
install -Dm644 "${srcdir}/${_src_app_dir}/dist/linux/common/org.cryptomator.Cryptomator.tray-unlocked.svg" "${pkgdir}/usr/share/icons/hicolor/symbolic/apps/org.cryptomator.Cryptomator.tray-unlocked-symbolic.svg"
|
|
||||||
|
|
||||||
mkdir -p "${pkgdir}/opt/cryptomator/"
|
|
||||||
cp -R "${srcdir}/${_src_app_dir}/target/cryptomator" "${pkgdir}/opt/"
|
|
||||||
install -Dm644 "${srcdir}/${_src_app_dir}/target/LICENSE.txt" -t "${pkgdir}/usr/share/licenses/${pkgname}"
|
|
||||||
|
|
||||||
mkdir -p "${pkgdir}/usr/bin"
|
|
||||||
ln -s "/opt/cryptomator/bin/cryptomator" "${pkgdir}/usr/bin/cryptomator"
|
|
||||||
}
|
|
||||||
@@ -1 +1,2 @@
|
|||||||
embedded.provisionprofile
|
embedded.provisionprofile
|
||||||
|
xcuserdata/
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
//
|
||||||
|
// CryptomatorDockTilePlugin.swift
|
||||||
|
// Integrations
|
||||||
|
//
|
||||||
|
// Created by Tobias Hagemann on 22.09.25.
|
||||||
|
// Copyright © 2025 Cryptomator. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import AppKit
|
||||||
|
|
||||||
|
class CryptomatorDockTilePlugin: NSObject, NSDockTilePlugIn {
|
||||||
|
func setDockTile(_ dockTile: NSDockTile?) {
|
||||||
|
guard let dockTile = dockTile, let image = Bundle(for: Self.self).image(forResource: "Cryptomator") else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
dockTile.contentView = NSImageView(image: image)
|
||||||
|
dockTile.display()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,314 @@
|
|||||||
|
// !$*UTF8*$!
|
||||||
|
{
|
||||||
|
archiveVersion = 1;
|
||||||
|
classes = {
|
||||||
|
};
|
||||||
|
objectVersion = 77;
|
||||||
|
objects = {
|
||||||
|
|
||||||
|
/* Begin PBXBuildFile section */
|
||||||
|
74E08DE12E8584DE007E665C /* CryptomatorDockTilePlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74E08DE02E85847E007E665C /* CryptomatorDockTilePlugin.swift */; };
|
||||||
|
74E08DED2E858532007E665C /* Cryptomator.icns in Resources */ = {isa = PBXBuildFile; fileRef = 74E08DEC2E858532007E665C /* Cryptomator.icns */; };
|
||||||
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
|
/* Begin PBXFileReference section */
|
||||||
|
74E08DD92E858467007E665C /* Cryptomator.docktileplugin */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Cryptomator.docktileplugin; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
74E08DE02E85847E007E665C /* CryptomatorDockTilePlugin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CryptomatorDockTilePlugin.swift; sourceTree = "<group>"; };
|
||||||
|
74E08DEC2E858532007E665C /* Cryptomator.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = Cryptomator.icns; path = ../resources/Cryptomator.icns; sourceTree = SOURCE_ROOT; };
|
||||||
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
|
74E08DD62E858467007E665C /* Frameworks */ = {
|
||||||
|
isa = PBXFrameworksBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXFrameworksBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXGroup section */
|
||||||
|
74E08DD02E858467007E665C = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
74E08DE02E85847E007E665C /* CryptomatorDockTilePlugin.swift */,
|
||||||
|
74E08DEC2E858532007E665C /* Cryptomator.icns */,
|
||||||
|
74E08DDA2E858467007E665C /* Products */,
|
||||||
|
);
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
74E08DDA2E858467007E665C /* Products */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
74E08DD92E858467007E665C /* Cryptomator.docktileplugin */,
|
||||||
|
);
|
||||||
|
name = Products;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
/* End PBXGroup section */
|
||||||
|
|
||||||
|
/* Begin PBXNativeTarget section */
|
||||||
|
74E08DD82E858467007E665C /* DockTilePlugin */ = {
|
||||||
|
isa = PBXNativeTarget;
|
||||||
|
buildConfigurationList = 74E08DDD2E858467007E665C /* Build configuration list for PBXNativeTarget "DockTilePlugin" */;
|
||||||
|
buildPhases = (
|
||||||
|
74E08DD52E858467007E665C /* Sources */,
|
||||||
|
74E08DD62E858467007E665C /* Frameworks */,
|
||||||
|
74E08DD72E858467007E665C /* Resources */,
|
||||||
|
);
|
||||||
|
buildRules = (
|
||||||
|
);
|
||||||
|
dependencies = (
|
||||||
|
);
|
||||||
|
name = DockTilePlugin;
|
||||||
|
packageProductDependencies = (
|
||||||
|
);
|
||||||
|
productName = DockTilePlugin;
|
||||||
|
productReference = 74E08DD92E858467007E665C /* Cryptomator.docktileplugin */;
|
||||||
|
productType = "com.apple.product-type.bundle";
|
||||||
|
};
|
||||||
|
/* End PBXNativeTarget section */
|
||||||
|
|
||||||
|
/* Begin PBXProject section */
|
||||||
|
74E08DD12E858467007E665C /* Project object */ = {
|
||||||
|
isa = PBXProject;
|
||||||
|
attributes = {
|
||||||
|
BuildIndependentTargetsInParallel = 1;
|
||||||
|
LastUpgradeCheck = 2600;
|
||||||
|
ORGANIZATIONNAME = Cryptomator;
|
||||||
|
TargetAttributes = {
|
||||||
|
74E08DD82E858467007E665C = {
|
||||||
|
CreatedOnToolsVersion = 26.0.1;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
buildConfigurationList = 74E08DD42E858467007E665C /* Build configuration list for PBXProject "DockTilePlugin" */;
|
||||||
|
developmentRegion = en;
|
||||||
|
hasScannedForEncodings = 0;
|
||||||
|
knownRegions = (
|
||||||
|
en,
|
||||||
|
Base,
|
||||||
|
);
|
||||||
|
mainGroup = 74E08DD02E858467007E665C;
|
||||||
|
minimizedProjectReferenceProxies = 1;
|
||||||
|
preferredProjectObjectVersion = 77;
|
||||||
|
productRefGroup = 74E08DDA2E858467007E665C /* Products */;
|
||||||
|
projectDirPath = "";
|
||||||
|
projectRoot = "";
|
||||||
|
targets = (
|
||||||
|
74E08DD82E858467007E665C /* DockTilePlugin */,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
/* End PBXProject section */
|
||||||
|
|
||||||
|
/* Begin PBXResourcesBuildPhase section */
|
||||||
|
74E08DD72E858467007E665C /* Resources */ = {
|
||||||
|
isa = PBXResourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
74E08DED2E858532007E665C /* Cryptomator.icns in Resources */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXResourcesBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXSourcesBuildPhase section */
|
||||||
|
74E08DD52E858467007E665C /* Sources */ = {
|
||||||
|
isa = PBXSourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
74E08DE12E8584DE007E665C /* CryptomatorDockTilePlugin.swift in Sources */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXSourcesBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin XCBuildConfiguration section */
|
||||||
|
74E08DDB2E858467007E665C /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
|
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||||
|
CLANG_ANALYZER_NONNULL = YES;
|
||||||
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CLANG_ENABLE_OBJC_ARC = YES;
|
||||||
|
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||||
|
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||||
|
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_COMMA = YES;
|
||||||
|
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||||
|
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||||
|
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||||
|
CLANG_WARN_EMPTY_BODY = YES;
|
||||||
|
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||||
|
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||||
|
CLANG_WARN_INT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||||
|
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||||
|
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||||
|
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||||
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
|
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||||
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
|
COPY_PHASE_STRIP = NO;
|
||||||
|
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||||
|
DEVELOPMENT_TEAM = YZQJQUHA3L;
|
||||||
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
|
ENABLE_TESTABILITY = YES;
|
||||||
|
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||||
|
GCC_DYNAMIC_NO_PIC = NO;
|
||||||
|
GCC_NO_COMMON_BLOCKS = YES;
|
||||||
|
GCC_OPTIMIZATION_LEVEL = 0;
|
||||||
|
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||||
|
"DEBUG=1",
|
||||||
|
"$(inherited)",
|
||||||
|
);
|
||||||
|
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||||
|
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||||
|
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||||
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
|
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
|
||||||
|
MACOSX_DEPLOYMENT_TARGET = 11.5;
|
||||||
|
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||||
|
MTL_FAST_MATH = YES;
|
||||||
|
ONLY_ACTIVE_ARCH = YES;
|
||||||
|
SDKROOT = macosx;
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
74E08DDC2E858467007E665C /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
|
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||||
|
CLANG_ANALYZER_NONNULL = YES;
|
||||||
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CLANG_ENABLE_OBJC_ARC = YES;
|
||||||
|
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||||
|
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||||
|
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_COMMA = YES;
|
||||||
|
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||||
|
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||||
|
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||||
|
CLANG_WARN_EMPTY_BODY = YES;
|
||||||
|
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||||
|
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||||
|
CLANG_WARN_INT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||||
|
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||||
|
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||||
|
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||||
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
|
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||||
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
|
COPY_PHASE_STRIP = NO;
|
||||||
|
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||||
|
DEVELOPMENT_TEAM = YZQJQUHA3L;
|
||||||
|
ENABLE_NS_ASSERTIONS = NO;
|
||||||
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
|
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||||
|
GCC_NO_COMMON_BLOCKS = YES;
|
||||||
|
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||||
|
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||||
|
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||||
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
|
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
|
||||||
|
MACOSX_DEPLOYMENT_TARGET = 11.5;
|
||||||
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
|
MTL_FAST_MATH = YES;
|
||||||
|
SDKROOT = macosx;
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
|
74E08DDE2E858467007E665C /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
CODE_SIGN_STYLE = Manual;
|
||||||
|
COMBINE_HIDPI_IMAGES = YES;
|
||||||
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
DEVELOPMENT_TEAM = "";
|
||||||
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2025 Cryptomator. All rights reserved.";
|
||||||
|
INFOPLIST_KEY_NSPrincipalClass = CryptomatorDockTilePlugin;
|
||||||
|
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles";
|
||||||
|
MARKETING_VERSION = 1.0;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = org.cryptomator.DockTilePlugin;
|
||||||
|
PRODUCT_NAME = Cryptomator;
|
||||||
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
||||||
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
WRAPPER_EXTENSION = docktileplugin;
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
74E08DDF2E858467007E665C /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
CODE_SIGN_STYLE = Manual;
|
||||||
|
COMBINE_HIDPI_IMAGES = YES;
|
||||||
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
DEVELOPMENT_TEAM = "";
|
||||||
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2025 Cryptomator. All rights reserved.";
|
||||||
|
INFOPLIST_KEY_NSPrincipalClass = CryptomatorDockTilePlugin;
|
||||||
|
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles";
|
||||||
|
MARKETING_VERSION = 1.0;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = org.cryptomator.DockTilePlugin;
|
||||||
|
PRODUCT_NAME = Cryptomator;
|
||||||
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
||||||
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
WRAPPER_EXTENSION = docktileplugin;
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
|
/* End XCBuildConfiguration section */
|
||||||
|
|
||||||
|
/* Begin XCConfigurationList section */
|
||||||
|
74E08DD42E858467007E665C /* Build configuration list for PBXProject "DockTilePlugin" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
74E08DDB2E858467007E665C /* Debug */,
|
||||||
|
74E08DDC2E858467007E665C /* Release */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
|
74E08DDD2E858467007E665C /* Build configuration list for PBXNativeTarget "DockTilePlugin" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
74E08DDE2E858467007E665C /* Debug */,
|
||||||
|
74E08DDF2E858467007E665C /* Release */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
|
/* End XCConfigurationList section */
|
||||||
|
};
|
||||||
|
rootObject = 74E08DD12E858467007E665C /* Project object */;
|
||||||
|
}
|
||||||
Generated
Vendored
+7
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Workspace
|
||||||
|
version = "1.0">
|
||||||
|
<FileRef
|
||||||
|
location = "self:">
|
||||||
|
</FileRef>
|
||||||
|
</Workspace>
|
||||||
Vendored
+67
@@ -0,0 +1,67 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Scheme
|
||||||
|
LastUpgradeVersion = "2600"
|
||||||
|
version = "1.7">
|
||||||
|
<BuildAction
|
||||||
|
parallelizeBuildables = "YES"
|
||||||
|
buildImplicitDependencies = "YES"
|
||||||
|
buildArchitectures = "Automatic">
|
||||||
|
<BuildActionEntries>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "74E08DD82E858467007E665C"
|
||||||
|
BuildableName = "Cryptomator.docktileplugin"
|
||||||
|
BlueprintName = "DockTilePlugin"
|
||||||
|
ReferencedContainer = "container:DockTilePlugin.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
</BuildActionEntries>
|
||||||
|
</BuildAction>
|
||||||
|
<TestAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
shouldAutocreateTestPlan = "YES">
|
||||||
|
</TestAction>
|
||||||
|
<LaunchAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
launchStyle = "0"
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
|
debugDocumentVersioning = "YES"
|
||||||
|
debugServiceExtension = "internal"
|
||||||
|
allowLocationSimulation = "YES">
|
||||||
|
</LaunchAction>
|
||||||
|
<ProfileAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
savedToolIdentifier = ""
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
debugDocumentVersioning = "YES">
|
||||||
|
<MacroExpansion>
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "74E08DD82E858467007E665C"
|
||||||
|
BuildableName = "Cryptomator.docktileplugin"
|
||||||
|
BlueprintName = "DockTilePlugin"
|
||||||
|
ReferencedContainer = "container:DockTilePlugin.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</MacroExpansion>
|
||||||
|
</ProfileAction>
|
||||||
|
<AnalyzeAction
|
||||||
|
buildConfiguration = "Debug">
|
||||||
|
</AnalyzeAction>
|
||||||
|
<ArchiveAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
revealArchiveInOrganizer = "YES">
|
||||||
|
</ArchiveAction>
|
||||||
|
</Scheme>
|
||||||
Vendored
+17
-5
@@ -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=25.0.2
|
JAVAFX_VERSION=25
|
||||||
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="4cd258001c75af7047005c5c891e2400ed11d24fbb09412324c0cbaf8b503c5a"
|
JAVAFX_JMODS_SHA256="13f8c0513c40c95881479fbcf0465a29a60217393fb0656f5e4eab78a9442fba"
|
||||||
else
|
else
|
||||||
JAVAFX_ARCH="x64"
|
JAVAFX_ARCH="x64"
|
||||||
JAVAFX_JMODS_SHA256="0b4d8463f03901b7425d94628e4116b7078abb8dd540fbec415266fac20bda5c"
|
JAVAFX_JMODS_SHA256="0eba73fb28a24c845175d16fa2f8c081c936ce6de1be9b79eb6119fa32e53d52"
|
||||||
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"
|
||||||
|
|
||||||
@@ -114,9 +114,9 @@ ${JAVA_HOME}/bin/jpackage \
|
|||||||
--java-options "-Dapple.awt.enableTemplateImages=true" \
|
--java-options "-Dapple.awt.enableTemplateImages=true" \
|
||||||
--java-options "-Dsun.java2d.metal=true" \
|
--java-options "-Dsun.java2d.metal=true" \
|
||||||
--java-options "-Dcryptomator.appVersion=\"${VERSION_NO}\"" \
|
--java-options "-Dcryptomator.appVersion=\"${VERSION_NO}\"" \
|
||||||
--java-options "-Dcryptomator.adminConfigPath=\"/Library/Application Support/Cryptomator/config.properties\"" \
|
|
||||||
--java-options "-Dcryptomator.logDir=\"@{userhome}/Library/Logs/${APP_NAME}\"" \
|
--java-options "-Dcryptomator.logDir=\"@{userhome}/Library/Logs/${APP_NAME}\"" \
|
||||||
--java-options "-XX:ErrorFile=/cryptomator/cryptomator_crash.log" \
|
--java-options "-XX:ErrorFile=/cryptomator/cryptomator_crash.log" \
|
||||||
|
--java-options "-Dcryptomator.pluginDir=\"@{userhome}/Library/Application Support/${APP_NAME}/Plugins\"" \
|
||||||
--java-options "-Dcryptomator.settingsPath=\"@{userhome}/Library/Application Support/${APP_NAME}/settings.json\"" \
|
--java-options "-Dcryptomator.settingsPath=\"@{userhome}/Library/Application Support/${APP_NAME}/settings.json\"" \
|
||||||
--java-options "-Dcryptomator.ipcSocketPath=\"@{userhome}/Library/Application Support/${APP_NAME}/ipc.socket\"" \
|
--java-options "-Dcryptomator.ipcSocketPath=\"@{userhome}/Library/Application Support/${APP_NAME}/ipc.socket\"" \
|
||||||
--java-options "-Dcryptomator.p12Path=\"@{userhome}/Library/Application Support/${APP_NAME}/key.p12\"" \
|
--java-options "-Dcryptomator.p12Path=\"@{userhome}/Library/Application Support/${APP_NAME}/key.p12\"" \
|
||||||
@@ -130,11 +130,23 @@ ${JAVA_HOME}/bin/jpackage \
|
|||||||
|
|
||||||
# transform app dir
|
# transform app dir
|
||||||
cp ../resources/${APP_NAME}-Vault.icns ${APP_NAME}.app/Contents/Resources/
|
cp ../resources/${APP_NAME}-Vault.icns ${APP_NAME}.app/Contents/Resources/
|
||||||
cp ../resources/Assets.car ${APP_NAME}.app/Contents/Resources/
|
|
||||||
sed -i '' "s|###BUNDLE_SHORT_VERSION_STRING###|${VERSION_NO}|g" ${APP_NAME}.app/Contents/Info.plist
|
sed -i '' "s|###BUNDLE_SHORT_VERSION_STRING###|${VERSION_NO}|g" ${APP_NAME}.app/Contents/Info.plist
|
||||||
sed -i '' "s|###BUNDLE_VERSION###|${REVISION_NO}|g" ${APP_NAME}.app/Contents/Info.plist
|
sed -i '' "s|###BUNDLE_VERSION###|${REVISION_NO}|g" ${APP_NAME}.app/Contents/Info.plist
|
||||||
cp ../embedded.provisionprofile ${APP_NAME}.app/Contents/
|
cp ../embedded.provisionprofile ${APP_NAME}.app/Contents/
|
||||||
|
|
||||||
|
# build and install dock tile plugin
|
||||||
|
echo "Building and installing Cryptomator.docktileplugin..."
|
||||||
|
DERIVED_DATA_PATH=../DockTilePlugin/build
|
||||||
|
xcodebuild -project ../DockTilePlugin/DockTilePlugin.xcodeproj \
|
||||||
|
-scheme DockTilePlugin \
|
||||||
|
-configuration Release \
|
||||||
|
-derivedDataPath ${DERIVED_DATA_PATH} \
|
||||||
|
-quiet \
|
||||||
|
clean build
|
||||||
|
mkdir -p ${APP_NAME}.app/Contents/PlugIns
|
||||||
|
cp -R ${DERIVED_DATA_PATH}/Build/Products/Release/Cryptomator.docktileplugin ${APP_NAME}.app/Contents/PlugIns/
|
||||||
|
rm -rf ${DERIVED_DATA_PATH}
|
||||||
|
|
||||||
# generate license
|
# generate license
|
||||||
mvn -B -f../../../pom.xml license:add-third-party \
|
mvn -B -f../../../pom.xml license:add-third-party \
|
||||||
-Dlicense.thirdPartyFilename=license.rtf \
|
-Dlicense.thirdPartyFilename=license.rtf \
|
||||||
|
|||||||
Vendored
BIN
Binary file not shown.
Vendored
+3
-2
@@ -12,8 +12,6 @@
|
|||||||
<string>Cryptomator</string>
|
<string>Cryptomator</string>
|
||||||
<key>CFBundleIconFile</key>
|
<key>CFBundleIconFile</key>
|
||||||
<string>Cryptomator.icns</string>
|
<string>Cryptomator.icns</string>
|
||||||
<key>CFBundleIconName</key>
|
|
||||||
<string>Cryptomator</string>
|
|
||||||
<key>CFBundleIdentifier</key>
|
<key>CFBundleIdentifier</key>
|
||||||
<string>org.cryptomator</string>
|
<string>org.cryptomator</string>
|
||||||
<key>CFBundleInfoDictionaryVersion</key>
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
@@ -119,5 +117,8 @@
|
|||||||
<!-- allow utilization of integrated GPU, see https://developer.apple.com/library/mac/qa/qa1734/_index.html -->
|
<!-- allow utilization of integrated GPU, see https://developer.apple.com/library/mac/qa/qa1734/_index.html -->
|
||||||
<key>NSSupportsAutomaticGraphicsSwitching</key>
|
<key>NSSupportsAutomaticGraphicsSwitching</key>
|
||||||
<true/>
|
<true/>
|
||||||
|
<!-- register dock tile plugin -->
|
||||||
|
<key>NSDockTilePlugIn</key>
|
||||||
|
<string>Cryptomator.docktileplugin</string>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
Vendored
+7
-9
@@ -34,20 +34,20 @@ if ((Get-Command "mvn" -ErrorAction SilentlyContinue) -eq $null)
|
|||||||
}
|
}
|
||||||
if ((Get-Command 'wix' -ErrorAction SilentlyContinue) -eq $null)
|
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.2)'
|
Write-Error 'Unable to find wix in your PATH (try: dotnet tool install --global wix --version 6.0.0)'
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
$wixExtensions = & wix.exe extension list --global | Out-String
|
$wixExtensions = & wix.exe extension list --global | Out-String
|
||||||
if ($wixExtensions -notmatch 'WixToolset.UI.wixext') {
|
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.2 --global)'
|
Write-Error 'Wix UI extension missing. Please install it with: wix.exe extension add WixToolset.UI.wixext/6.0.0 --global)'
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
if ($wixExtensions -notmatch 'WixToolset.Util.wixext') {
|
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.2 --global)'
|
Write-Error 'Wix Util extension missing. Please install it with: wix.exe extension add WixToolset.Util.wixext/6.0.0 --global)'
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
if ($wixExtensions -notmatch 'WixToolset.BootstrapperApplications.wixext') {
|
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.2 --global)'
|
Write-Error 'Wix Bootstrapper extension missing. Please install it with: wix.exe extension add WixToolset.BootstrapperApplications.wixext/6.0.0 --global)'
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,9 +93,9 @@ switch ($archName) {
|
|||||||
$jmodPaths = "$Env:JAVA_HOME/jmods"
|
$jmodPaths = "$Env:JAVA_HOME/jmods"
|
||||||
}
|
}
|
||||||
'x64' {
|
'x64' {
|
||||||
$javaFxVersion='25.0.2'
|
$javaFxVersion='25'
|
||||||
$javaFxJmodsUrl = "https://download2.gluonhq.com/openjfx/${javaFxVersion}/openjfx-${javaFxVersion}_windows-x64_bin-jmods.zip"
|
$javaFxJmodsUrl = "https://download2.gluonhq.com/openjfx/${javaFxVersion}/openjfx-${javaFxVersion}_windows-x64_bin-jmods.zip"
|
||||||
$javaFxJmodsSHA256 = '33d878dfac85590c4d77c518ed413e512d34a8479d90132b230a7ddd173576b3'
|
$javaFxJmodsSHA256 = 'c8eb9fd039b00e0020cf6c3db8ed7876bf3ee4d27860aa697a247b83b8296ae7'
|
||||||
$javaFxJmods = '.\resources\jfxJmods.zip'
|
$javaFxJmods = '.\resources\jfxJmods.zip'
|
||||||
|
|
||||||
if( !(Test-Path -Path $javaFxJmods) ) {
|
if( !(Test-Path -Path $javaFxJmods) ) {
|
||||||
@@ -155,7 +155,7 @@ $javaOptions = @(
|
|||||||
"--java-options", "-Djava.net.useSystemProxies=true"
|
"--java-options", "-Djava.net.useSystemProxies=true"
|
||||||
"--java-options", "-Dcryptomator.logDir=`"@{localappdata}/$AppName`""
|
"--java-options", "-Dcryptomator.logDir=`"@{localappdata}/$AppName`""
|
||||||
"--java-options", "-XX:ErrorFile=`"C:/cryptomator/cryptomator_crash.log`""
|
"--java-options", "-XX:ErrorFile=`"C:/cryptomator/cryptomator_crash.log`""
|
||||||
"--java-options", "-Dcryptomator.adminConfigPath=`"C:/ProgramData/$AppName/config.properties`""
|
"--java-options", "-Dcryptomator.pluginDir=`"@{appdata}/$AppName/Plugins`""
|
||||||
"--java-options", "-Dcryptomator.settingsPath=`"@{appdata}/$AppName/settings.json;@{userhome}/AppData/Roaming/$AppName/settings.json`""
|
"--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.ipcSocketPath=`"@{localappdata}/$AppName/ipc.socket`""
|
||||||
"--java-options", "-Dcryptomator.p12Path=`"@{appdata}/$AppName/key.p12;@{userhome}/AppData/Roaming/$AppName/key.p12`""
|
"--java-options", "-Dcryptomator.p12Path=`"@{appdata}/$AppName/key.p12;@{userhome}/AppData/Roaming/$AppName/key.p12`""
|
||||||
@@ -221,10 +221,8 @@ $Env:JP_WIXHELPER_DIR = "."
|
|||||||
--vendor $Vendor `
|
--vendor $Vendor `
|
||||||
--copyright $copyright `
|
--copyright $copyright `
|
||||||
--app-version "$semVerNo.$revisionNo" `
|
--app-version "$semVerNo.$revisionNo" `
|
||||||
--win-menu `
|
|
||||||
--win-dir-chooser `
|
--win-dir-chooser `
|
||||||
--win-shortcut-prompt `
|
--win-shortcut-prompt `
|
||||||
--win-menu-group $AppName `
|
|
||||||
--resource-dir resources `
|
--resource-dir resources `
|
||||||
--license-file resources/license.rtf `
|
--license-file resources/license.rtf `
|
||||||
--win-update-url $UpdateUrl `
|
--win-update-url $UpdateUrl `
|
||||||
|
|||||||
-12
@@ -1,12 +0,0 @@
|
|||||||
@echo off
|
|
||||||
:: Batch wrapper for PowerShell script to disable user configuration in Cryptomator
|
|
||||||
:: This is executed as a Custom Action during MSI installation
|
|
||||||
:: This file must be located in the INSTALLDIR
|
|
||||||
|
|
||||||
:: Change to INSTALLDIR
|
|
||||||
cd %~dp0
|
|
||||||
:: Execute the PowerShell script
|
|
||||||
powershell.exe -NoLogo -NoProfile -NonInteractive -ExecutionPolicy RemoteSigned -File ".\disableUserConfig.ps1"
|
|
||||||
|
|
||||||
:: Return the exit code from PowerShell
|
|
||||||
exit /b %ERRORLEVEL%
|
|
||||||
-24
@@ -1,24 +0,0 @@
|
|||||||
# PowerShell script to disable user configuration
|
|
||||||
# This script is executed as a Custom Action during MSI installation
|
|
||||||
# It deletes the file .package, effectively disabling user specific jpackage configuration.
|
|
||||||
# NOTE: This file must be located in the same directory as set in the MSI property INSTALLDIR
|
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
# Determine file path
|
|
||||||
$packageFile = Join-Path $PSScriptRoot 'app\.package'
|
|
||||||
|
|
||||||
#check if file exists
|
|
||||||
if (Test-Path -Path $packageFile) {
|
|
||||||
Write-Host "Deleting file: $packageFile"
|
|
||||||
Remove-Item -Path $packageFile -Force -ErrorAction Stop
|
|
||||||
} else {
|
|
||||||
Write-Host "File not found: $packageFile. Skipping deletion."
|
|
||||||
}
|
|
||||||
|
|
||||||
exit 0
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
Write-Error "Error deleting package file: $_"
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
Vendored
+67
-85
@@ -1,11 +1,11 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<ns0:Wix xmlns:ns0="http://wixtoolset.org/schemas/v4/wxs" xmlns:util="http://wixtoolset.org/schemas/v4/wxs/util" >
|
<ns0:Wix xmlns:ns0="http://wixtoolset.org/schemas/v4/wxs" xmlns:util="http://wixtoolset.org/schemas/v4/wxs/util">
|
||||||
|
|
||||||
<?ifdef JpIsSystemWide ?>
|
<?ifdef JpIsSystemWide ?>
|
||||||
<?define JpInstallScope="perMachine"?>
|
<?define JpInstallScope="perMachine"?>
|
||||||
<?else?>
|
<?else ?>
|
||||||
<?define JpInstallScope="perUser"?>
|
<?define JpInstallScope="perUser"?>
|
||||||
<?endif?>
|
<?endif ?>
|
||||||
|
|
||||||
<?define JpProductLanguage=1033 ?>
|
<?define JpProductLanguage=1033 ?>
|
||||||
<?define JpInstallerVersion=200 ?>
|
<?define JpInstallerVersion=200 ?>
|
||||||
@@ -13,20 +13,21 @@
|
|||||||
|
|
||||||
<?ifdef JpAllowUpgrades ?>
|
<?ifdef JpAllowUpgrades ?>
|
||||||
<?define JpUpgradeVersionOnlyDetectUpgrade="no"?>
|
<?define JpUpgradeVersionOnlyDetectUpgrade="no"?>
|
||||||
<?else?>
|
<?else ?>
|
||||||
<?define JpUpgradeVersionOnlyDetectUpgrade="yes"?>
|
<?define JpUpgradeVersionOnlyDetectUpgrade="yes"?>
|
||||||
<?endif?>
|
<?endif ?>
|
||||||
<?ifdef JpAllowDowngrades ?>
|
<?ifdef JpAllowDowngrades ?>
|
||||||
<?define JpUpgradeVersionOnlyDetectDowngrade="no"?>
|
<?define JpUpgradeVersionOnlyDetectDowngrade="no"?>
|
||||||
<?else?>
|
<?else ?>
|
||||||
<?define JpUpgradeVersionOnlyDetectDowngrade="yes"?>
|
<?define JpUpgradeVersionOnlyDetectDowngrade="yes"?>
|
||||||
<?endif?>
|
<?endif ?>
|
||||||
|
|
||||||
<!-- Cryptomator defaults -->
|
<!-- Cryptomator defaults -->
|
||||||
<?define IconFileEncryptedData= "Cryptomator-Vault.ico" ?>
|
<?define IconFileEncryptedData= "Cryptomator-Vault.ico" ?>
|
||||||
<?define ProgIdContentType= "application/vnd.cryptomator.encrypted" ?>
|
<?define ProgIdContentType= "application/vnd.cryptomator.encrypted" ?>
|
||||||
<?define CloseApplicationTarget= "cryptomator.exe" ?>
|
<?define CloseApplicationTarget= "cryptomator.exe" ?>
|
||||||
<?define LoopbackAlias= "cryptomator-vault" ?>
|
<?define LoopbackAlias= "cryptomator-vault" ?>
|
||||||
|
<?define AppUserModelId= "Cryptomator.Cryptomator" ?>
|
||||||
|
|
||||||
<?include $(var.JpConfigDir)/overrides.wxi ?>
|
<?include $(var.JpConfigDir)/overrides.wxi ?>
|
||||||
|
|
||||||
@@ -42,8 +43,7 @@
|
|||||||
Scope="$(var.JpInstallScope)">
|
Scope="$(var.JpInstallScope)">
|
||||||
|
|
||||||
<ns0:SummaryInformation Manufacturer="$(var.JpAppVendor)" Description="$(var.JpAppDescription)"/>
|
<ns0:SummaryInformation Manufacturer="$(var.JpAppVendor)" Description="$(var.JpAppDescription)"/>
|
||||||
<ns0:Media Id="1" Cabinet="Data.cab" EmbedCab="yes" />
|
<ns0:Media Id="1" Cabinet="Data.cab" EmbedCab="yes"/>
|
||||||
|
|
||||||
|
|
||||||
<ns0:Upgrade Id="$(var.JpProductUpgradeCode)">
|
<ns0:Upgrade Id="$(var.JpProductUpgradeCode)">
|
||||||
<ns0:UpgradeVersion
|
<ns0:UpgradeVersion
|
||||||
@@ -51,34 +51,34 @@
|
|||||||
Property="JP_UPGRADABLE_FOUND"
|
Property="JP_UPGRADABLE_FOUND"
|
||||||
Maximum="$(var.JpAppVersion)"
|
Maximum="$(var.JpAppVersion)"
|
||||||
MigrateFeatures="yes"
|
MigrateFeatures="yes"
|
||||||
IncludeMaximum="$(var.JpUpgradeVersionOnlyDetectUpgrade)"/> <!-- TODO in earlier versions, this was set to yes-->
|
IncludeMaximum="$(var.JpUpgradeVersionOnlyDetectUpgrade)"/>
|
||||||
<ns0: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)"/>
|
||||||
</ns0:Upgrade>
|
</ns0:Upgrade>
|
||||||
|
|
||||||
<?ifndef JpAllowUpgrades ?>
|
<?ifndef JpAllowUpgrades ?>
|
||||||
<ns0:CustomAction Id="JpDisallowUpgrade" Error="!(loc.DisallowUpgradeErrorMessage)" />
|
<ns0:CustomAction Id="JpDisallowUpgrade" Error="!(loc.DisallowUpgradeErrorMessage)"/>
|
||||||
<?endif?>
|
<?endif ?>
|
||||||
<?ifndef JpAllowDowngrades ?>
|
<?ifndef JpAllowDowngrades ?>
|
||||||
<ns0:CustomAction Id="JpDisallowDowngrade" Error="!(loc.DowngradeErrorMessage)" />
|
<ns0:CustomAction Id="JpDisallowDowngrade" Error="!(loc.DowngradeErrorMessage)"/>
|
||||||
<?endif?>
|
<?endif ?>
|
||||||
|
|
||||||
<!-- TODO: how does this work again? -->
|
<!-- in order to sign the DLL, the path to the dll can be specified -->
|
||||||
<ns0:Binary Id="JpCaDll" SourceFile="$(env.JP_WIXHELPER_DIR)\wixhelper.dll" />
|
<ns0:Binary Id="JpCaDll" SourceFile="$(env.JP_WIXHELPER_DIR)\wixhelper.dll"/>
|
||||||
<ns0:CustomAction Id="JpFindRelatedProducts" BinaryRef="JpCaDll" DllEntry="FindRelatedProductsEx" />
|
<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 -->
|
||||||
<ns0:Property Id="OLDEXEINSTALLER">
|
<ns0:Property Id="OLDEXEINSTALLER">
|
||||||
<ns0: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" />
|
||||||
</ns0:Property>
|
</ns0:Property>
|
||||||
<!-- TODO: localize -->
|
|
||||||
<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" />
|
<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" />
|
||||||
<?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-->
|
||||||
<ns0:Property Id="WINDOWSBUILDNUMBER" Secure="yes">
|
<ns0:Property Id="WINDOWSBUILDNUMBER" Secure="yes">
|
||||||
<ns0: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" />
|
||||||
@@ -87,7 +87,7 @@
|
|||||||
|
|
||||||
<!-- Non-Opening ProgID -->
|
<!-- Non-Opening ProgID -->
|
||||||
<ns0:DirectoryRef Id="INSTALLDIR">
|
<ns0:DirectoryRef Id="INSTALLDIR">
|
||||||
<ns0:Component Bitness="always64" Id="nonStartingProgID">
|
<ns0:Component Bitness="always64" Id="NonStartingProgID" >
|
||||||
<ns0:File Id="IconFileForEncryptedData" KeyPath="yes" Source="$(env.JP_WIXWIZARD_RESOURCES)\$(var.IconFileEncryptedData)" Name="$(var.IconFileEncryptedData)"/>
|
<ns0:File Id="IconFileForEncryptedData" KeyPath="yes" Source="$(env.JP_WIXWIZARD_RESOURCES)\$(var.IconFileEncryptedData)" Name="$(var.IconFileEncryptedData)"/>
|
||||||
<ns0: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">
|
||||||
<ns0:Extension Id="c9r" Advertise="no" ContentType="$(var.ProgIdContentType)">
|
<ns0:Extension Id="c9r" Advertise="no" ContentType="$(var.ProgIdContentType)">
|
||||||
@@ -99,35 +99,24 @@
|
|||||||
</ns0:Component>
|
</ns0:Component>
|
||||||
</ns0:DirectoryRef>
|
</ns0:DirectoryRef>
|
||||||
|
|
||||||
<ns0:StandardDirectory Id="CommonAppDataFolder">
|
<ns0:DirectoryRef Id="ProgramMenuFolder">
|
||||||
<ns0:Directory Id="CryptomatorDesktopProgramData" Name="Cryptomator">
|
<!-- Shortcut with set AUMID -->
|
||||||
<ns0:Component Id="AdminConfigDir" Guid="c078b7da-ba6e-4069-a5ab-5c0f0f9856a0">
|
<ns0:Component Guid="{88290d4b-0b71-4568-a4b6-70d6b0498c9c}" Bitness="always64" Id="CustomShortcuts">
|
||||||
<ns0:CreateFolder>
|
<ns0:RegistryKey Root="HKLM" Key="Software\$(var.JpAppVendor)\$(var.JpAppName)\$(var.JpAppVersion)">
|
||||||
<util:PermissionEx User="SYSTEM" GenericAll="yes"/>
|
<ns0:RegistryValue Type="string" KeyPath="yes" Name="ProductCode" Value="[ProductCode]"/>
|
||||||
<util:PermissionEx User="Administrators" GenericAll="yes"/>
|
</ns0:RegistryKey>
|
||||||
<util:PermissionEx User="Users" GenericRead="yes" GenericExecute="yes"/>
|
<ns0:Shortcut Id="appShortcut" Name="$(var.JpAppName)" Advertise="no" Target="[INSTALLDIR]$(var.JpAppName).exe">
|
||||||
</ns0:CreateFolder>
|
<ns0:ShortcutProperty Key="System.AppUserModel.ID" Value="$(var.AppUserModelId)"/>
|
||||||
|
</ns0:Shortcut>
|
||||||
</ns0:Component>
|
</ns0:Component>
|
||||||
<ns0:Component Id="AdminConfigFile" NeverOverwrite="yes" Permanent="yes">
|
</ns0:DirectoryRef>
|
||||||
<ns0:File Id="EmptyAdminConfig" Source="$(env.JP_WIXWIZARD_RESOURCES)\..\..\common\config.properties" Name="config.properties" KeyPath="yes">
|
|
||||||
<util:PermissionEx User="SYSTEM" GenericAll="yes"/>
|
|
||||||
<util:PermissionEx User="Administrators" GenericAll="yes"/>
|
|
||||||
<util:PermissionEx User="Users" GenericRead="yes" GenericExecute="yes"/>
|
|
||||||
</ns0:File>
|
|
||||||
</ns0:Component>
|
|
||||||
</ns0:Directory>
|
|
||||||
</ns0:StandardDirectory>
|
|
||||||
|
|
||||||
<!-- Standard required root -->
|
<!-- Standard required root -->
|
||||||
|
|
||||||
<ns0:Feature Id="DefaultFeature" Title="!(loc.MainFeatureTitle)" Level="1">
|
<ns0:Feature Id="DefaultFeature" Title="!(loc.MainFeatureTitle)" Level="1">
|
||||||
<ns0:ComponentGroupRef Id="Shortcuts"/>
|
|
||||||
<ns0:ComponentGroupRef Id="Files"/>
|
<ns0:ComponentGroupRef Id="Files"/>
|
||||||
<ns0:ComponentGroupRef Id="FileAssociations"/>
|
<ns0:ComponentGroupRef Id="FileAssociations"/>
|
||||||
<!-- Ref to additional ProgIDs -->
|
<ns0:ComponentRef Id="NonStartingProgID" />
|
||||||
<ns0:ComponentRef Id="nonStartingProgID"/>
|
<ns0:ComponentRef Id="CustomShortcuts" />
|
||||||
<ns0:ComponentRef Id="AdminConfigDir"/>
|
|
||||||
<ns0:ComponentRef Id="AdminConfigFile"/>
|
|
||||||
</ns0:Feature>
|
</ns0:Feature>
|
||||||
|
|
||||||
<ns0:CustomAction Id="JpSetARPINSTALLLOCATION" Property="ARPINSTALLLOCATION" Value="[INSTALLDIR]" />
|
<ns0:CustomAction Id="JpSetARPINSTALLLOCATION" Property="ARPINSTALLLOCATION" Value="[INSTALLDIR]" />
|
||||||
@@ -136,33 +125,31 @@
|
|||||||
<ns0:CustomAction Id="JpSetARPSIZE" Property="ARPSIZE" Value="$(var.JpAppSizeKb)" />
|
<ns0:CustomAction Id="JpSetARPSIZE" Property="ARPSIZE" Value="$(var.JpAppSizeKb)" />
|
||||||
|
|
||||||
<?ifdef JpHelpURL ?>
|
<?ifdef JpHelpURL ?>
|
||||||
<ns0:CustomAction Id="JpSetARPHELPLINK" Property="ARPHELPLINK" Value="$(var.JpHelpURL)" />
|
<ns0:CustomAction Id="JpSetARPHELPLINK" Property="ARPHELPLINK" Value="$(var.JpHelpURL)"/>
|
||||||
<?endif?>
|
<?endif ?>
|
||||||
|
|
||||||
<?ifdef JpAboutURL ?>
|
<?ifdef JpAboutURL ?>
|
||||||
<ns0:CustomAction Id="JpSetARPURLINFOABOUT" Property="ARPURLINFOABOUT" Value="$(var.JpAboutURL)" />
|
<ns0:CustomAction Id="JpSetARPURLINFOABOUT" Property="ARPURLINFOABOUT" Value="$(var.JpAboutURL)"/>
|
||||||
<?endif?>
|
<?endif ?>
|
||||||
|
|
||||||
<?ifdef JpUpdateURL ?>
|
<?ifdef JpUpdateURL ?>
|
||||||
<ns0:CustomAction Id="JpSetARPURLUPDATEINFO" Property="ARPURLUPDATEINFO" Value="$(var.JpUpdateURL)" />
|
<ns0:CustomAction Id="JpSetARPURLUPDATEINFO" Property="ARPURLUPDATEINFO" Value="$(var.JpUpdateURL)"/>
|
||||||
<?endif?>
|
<?endif ?>
|
||||||
|
|
||||||
|
<?ifdef JpIcon ?>
|
||||||
|
<ns0:Property Id="ARPPRODUCTICON" Value="JpARPPRODUCTICON"/>
|
||||||
|
<ns0:Icon Id="JpARPPRODUCTICON" SourceFile="$(var.JpIcon)"/>
|
||||||
|
<?endif ?>
|
||||||
|
|
||||||
<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.-->
|
||||||
|
<ns0:Property Id="WixQuietExec64CmdTimeout" Value="20"/>
|
||||||
<!-- Property for controlling update check behavior (can be set via command line) -->
|
<!-- Property for controlling update check behavior (can be set via command line) -->
|
||||||
<ns0:Property Id="DISABLEUPDATECHECK" Secure="yes" />
|
<ns0:Property Id="DISABLEUPDATECHECK" Secure="yes"/>
|
||||||
|
|
||||||
<!-- Disable user config -->
|
|
||||||
<ns0:SetProperty Id="DisableUserConfig" Value=""[INSTALLDIR]disableUserConfig.bat"" Sequence="execute" Before="DisableUserConfig" />
|
|
||||||
<ns0:CustomAction Id="DisableUserConfig" BinaryRef="Wix4UtilCA_$(sys.BUILDARCHSHORT)" DllEntry="WixQuietExec" Execute="deferred" Return="ignore" Impersonate="no"/>
|
|
||||||
|
|
||||||
<!-- WebDAV patches -->
|
<!-- WebDAV patches -->
|
||||||
<ns0:SetProperty Id="PatchWebDAV" Value=""[INSTALLDIR]patchWebDAV.bat" "$(var.LoopbackAlias)"" Sequence="execute" Before="PatchWebDAV" />
|
<ns0:SetProperty Id="PatchWebDAV" Value=""[INSTALLDIR]patchWebDAV.bat" "$(var.LoopbackAlias)"" Sequence="execute" Before="PatchWebDAV"/>
|
||||||
<ns0:CustomAction Id="PatchWebDAV" BinaryRef="Wix4UtilCA_$(sys.BUILDARCHSHORT)" DllEntry="WixQuietExec" Execute="deferred" Return="ignore" Impersonate="no"/>
|
<ns0:CustomAction Id="PatchWebDAV" BinaryRef="Wix4UtilCA_$(sys.BUILDARCHSHORT)" DllEntry="WixQuietExec" Execute="deferred" Return="ignore" Impersonate="no"/>
|
||||||
|
|
||||||
<!-- Update check configuration -->
|
<!-- Update check configuration -->
|
||||||
<ns0:SetProperty Id="PatchUpdateCheck" Value=""[INSTALLDIR]patchUpdateCheck.bat" "[DISABLEUPDATECHECK]"" Sequence="execute" Before="PatchUpdateCheck" />
|
<ns0:SetProperty Id="PatchUpdateCheck" Value=""[INSTALLDIR]patchUpdateCheck.bat" "[DISABLEUPDATECHECK]"" Sequence="execute" Before="PatchUpdateCheck"/>
|
||||||
<ns0:CustomAction Id="PatchUpdateCheck" BinaryRef="Wix4UtilCA_$(sys.BUILDARCHSHORT)" DllEntry="WixQuietExec64" Execute="deferred" Return="ignore" Impersonate="no"/>
|
<ns0:CustomAction Id="PatchUpdateCheck" BinaryRef="Wix4UtilCA_$(sys.BUILDARCHSHORT)" DllEntry="WixQuietExec64" Execute="deferred" Return="ignore" Impersonate="no"/>
|
||||||
|
|
||||||
<!-- Running App detection and exit -->
|
<!-- Running App detection and exit -->
|
||||||
@@ -178,45 +165,40 @@
|
|||||||
/>
|
/>
|
||||||
<ns0:CustomAction Id="FailOnRunningApp" Error="Installation aborted, because files marked for update are used by a running instance of $(var.JpAppName)."/>
|
<ns0:CustomAction Id="FailOnRunningApp" Error="Installation aborted, because files marked for update are used by a running instance of $(var.JpAppName)."/>
|
||||||
|
|
||||||
<?ifdef JpIcon ?>
|
|
||||||
<ns0:Property Id="ARPPRODUCTICON" Value="JpARPPRODUCTICON"/>
|
|
||||||
<ns0:Icon Id="JpARPPRODUCTICON" SourceFile="$(var.JpIcon)"/>
|
|
||||||
<?endif?>
|
|
||||||
|
|
||||||
<ns0:UIRef Id="JpUI"/>
|
<ns0:UIRef Id="JpUI"/>
|
||||||
|
|
||||||
<ns0:InstallExecuteSequence>
|
<ns0:InstallExecuteSequence>
|
||||||
<ns0:Custom Action="JpSetARPINSTALLLOCATION" After="CostFinalize" Condition="Not Installed" />
|
<ns0:Custom Action="JpSetARPINSTALLLOCATION" After="CostFinalize" Condition="Not Installed"/>
|
||||||
<ns0:Custom Action="JpSetARPCOMMENTS" After="CostFinalize" Condition="Not Installed" />
|
<ns0:Custom Action="JpSetARPCOMMENTS" After="CostFinalize" Condition="Not Installed"/>
|
||||||
<ns0:Custom Action="JpSetARPCONTACT" After="CostFinalize" Condition="Not Installed" />
|
<ns0:Custom Action="JpSetARPCONTACT" After="CostFinalize" Condition="Not Installed"/>
|
||||||
<ns0:Custom Action="JpSetARPSIZE" After="CostFinalize" Condition="Not Installed" />
|
<ns0:Custom Action="JpSetARPSIZE" After="CostFinalize" Condition="Not Installed"/>
|
||||||
<?ifdef JpHelpURL ?>
|
<?ifdef JpHelpURL ?>
|
||||||
<ns0:Custom Action="JpSetARPHELPLINK" After="CostFinalize" Condition="Not Installed" />
|
<ns0:Custom Action="JpSetARPHELPLINK" After="CostFinalize" Condition="Not Installed"/>
|
||||||
<?endif?>
|
<?endif ?>
|
||||||
<?ifdef JpAboutURL ?>
|
<?ifdef JpAboutURL ?>
|
||||||
<ns0:Custom Action="JpSetARPURLINFOABOUT" After="CostFinalize" Condition="Not Installed" />
|
<ns0:Custom Action="JpSetARPURLINFOABOUT" After="CostFinalize" Condition="Not Installed"/>
|
||||||
<?endif?>
|
<?endif ?>
|
||||||
<?ifdef JpUpdateURL ?>
|
<?ifdef JpUpdateURL ?>
|
||||||
<ns0:Custom Action="JpSetARPURLUPDATEINFO" After="CostFinalize" Condition="Not Installed" />
|
<ns0:Custom Action="JpSetARPURLUPDATEINFO" After="CostFinalize" Condition="Not Installed"/>
|
||||||
<?endif?>
|
<?endif ?>
|
||||||
|
|
||||||
<?ifndef JpAllowUpgrades ?>
|
<?ifndef JpAllowUpgrades ?>
|
||||||
<ns0:Custom Action="JpDisallowUpgrade" After="JpFindRelatedProducts" Condition="JP_UPGRADABLE_FOUND"/>
|
<ns0:Custom Action="JpDisallowUpgrade" After="JpFindRelatedProducts" Condition="JP_UPGRADABLE_FOUND"/>
|
||||||
<?endif?>
|
<?endif ?>
|
||||||
<?ifndef JpAllowDowngrades ?>
|
<?ifndef JpAllowDowngrades ?>
|
||||||
<ns0:Custom Action="JpDisallowDowngrade" After="JpFindRelatedProducts" Condition="JP_DOWNGRADABLE_FOUND" />
|
<ns0:Custom Action="JpDisallowDowngrade" After="JpFindRelatedProducts" Condition="JP_DOWNGRADABLE_FOUND"/>
|
||||||
<?endif?>
|
<?endif ?>
|
||||||
|
<ns0:LaunchConditions Before="AppSearch"></ns0:LaunchConditions>
|
||||||
<ns0: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 -->
|
||||||
<ns0:Custom Action="override Wix4CloseApplications_$(sys.BUILDARCHSHORT)" Before="InstallValidate" />
|
<ns0:Custom Action="override Wix4CloseApplications_$(sys.BUILDARCHSHORT)" Before="InstallValidate"/>
|
||||||
<ns0:Custom Action="FailOnRunningApp" After="Wix4CloseApplications_$(sys.BUILDARCHSHORT)" Condition="FOUNDRUNNINGAPP" />
|
<ns0:Custom Action="FailOnRunningApp" After="Wix4CloseApplications_$(sys.BUILDARCHSHORT)" Condition="FOUNDRUNNINGAPP"/>
|
||||||
|
|
||||||
<ns0:RemoveExistingProducts After="InstallValidate"/> <!-- Moved from CostInitialize, due to Wix4CloseApplications_* -->
|
<ns0:RemoveExistingProducts After="InstallValidate"/> <!-- Moved from CostInitialize, due to Wix4CloseApplications_* -->
|
||||||
<ns0:Custom Action="DisableUserConfig" After="InstallFiles" Condition="NOT (Installed AND (NOT REINSTALL) AND (NOT UPGRADINGPRODUCTCODE) AND REMOVE)"/>
|
|
||||||
<!-- Skip action on uninstall -->
|
<!-- Skip action on uninstall -->
|
||||||
<!-- TODO: don't skip action, but remove cryptomator alias from hosts file -->
|
<!-- TODO: don't skip action, but remove cryptomator alias from hosts file -->
|
||||||
<ns0:Custom Action="PatchWebDAV" After="DisableUserConfig" Condition="NOT (Installed AND (NOT REINSTALL) AND (NOT UPGRADINGPRODUCTCODE) AND REMOVE)"/>
|
<ns0:Custom Action="PatchWebDAV" After="InstallFiles" Condition="NOT (Installed AND (NOT REINSTALL) AND (NOT UPGRADINGPRODUCTCODE) AND REMOVE)"/>
|
||||||
<!-- Configure update check setting if property is provided -->
|
<!-- Configure update check setting if property is provided -->
|
||||||
<ns0:Custom Action="PatchUpdateCheck" After="PatchWebDAV" Condition="DISABLEUPDATECHECK AND NOT (Installed AND (NOT REINSTALL) AND (NOT UPGRADINGPRODUCTCODE) AND REMOVE)"/>
|
<ns0:Custom Action="PatchUpdateCheck" After="PatchWebDAV" Condition="DISABLEUPDATECHECK AND NOT (Installed AND (NOT REINSTALL) AND (NOT UPGRADINGPRODUCTCODE) AND REMOVE)"/>
|
||||||
</ns0:InstallExecuteSequence>
|
</ns0:InstallExecuteSequence>
|
||||||
@@ -225,7 +207,7 @@
|
|||||||
<ns0:Custom Action="JpFindRelatedProducts" After="FindRelatedProducts"/>
|
<ns0:Custom Action="JpFindRelatedProducts" After="FindRelatedProducts"/>
|
||||||
</ns0:InstallUISequence>
|
</ns0:InstallUISequence>
|
||||||
|
|
||||||
<ns0:WixVariable Id="WixUIBannerBmp" Value="$(env.JP_WIXWIZARD_RESOURCES)\banner.bmp" />
|
<ns0:WixVariable Id="WixUIBannerBmp" Value="$(env.JP_WIXWIZARD_RESOURCES)\banner.bmp"/>
|
||||||
<ns0:WixVariable Id="WixUIDialogBmp" Value="$(env.JP_WIXWIZARD_RESOURCES)\background.bmp" />
|
<ns0:WixVariable Id="WixUIDialogBmp" Value="$(env.JP_WIXWIZARD_RESOURCES)\background.bmp"/>
|
||||||
</ns0:Package>
|
</ns0:Package>
|
||||||
</ns0:Wix>
|
</ns0:Wix>
|
||||||
Vendored
+5
-6
@@ -18,17 +18,16 @@ Value of `Language` attribute of `Product` WiX element. Default value is 1033.
|
|||||||
- JpInstallerVersion
|
- JpInstallerVersion
|
||||||
Value of `InstallerVersion` attribute of `Package` WiX element. Default value is 200.
|
Value of `InstallerVersion` attribute of `Package` WiX element. Default value is 200.
|
||||||
|
|
||||||
- JpCompressedMsi
|
|
||||||
Value of `Compressed` attribute of `Package` WiX element. Default value is `yes`.
|
|
||||||
|
|
||||||
- JpAllowDowngrades
|
- JpAllowDowngrades
|
||||||
Should be defined to enable downgrades and undefined to disable downgrades.
|
Should be defined to enable downgrades and undefined to disable downgrades.
|
||||||
Default value is `yes`.
|
By default it is defined for applications and undefined for Runtime installer.
|
||||||
|
Use <?define JpAllowUpgrades = "foo" ?> to enable or <?undef JpAllowUpgrades?>
|
||||||
|
to disable (the value doesn't matter).
|
||||||
|
|
||||||
- JpAllowUpgrades
|
- JpAllowUpgrades
|
||||||
Should be defined to enable upgrades and undefined to disable upgrades.
|
Should be defined to enable upgrades and undefined to disable upgrades.
|
||||||
Default value is `yes`.
|
By default it is defined, use <?undef JpAllowUpgrades?> to disable. -->
|
||||||
-->
|
|
||||||
|
|
||||||
<!-- Cryptomator Section
|
<!-- Cryptomator Section
|
||||||
|
|
||||||
|
|||||||
@@ -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.19.0</version>
|
<version>1.19.0-SNAPSHOT</version>
|
||||||
<name>Cryptomator Desktop App</name>
|
<name>Cryptomator Desktop App</name>
|
||||||
|
|
||||||
<organization>
|
<organization>
|
||||||
@@ -33,46 +33,43 @@
|
|||||||
<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.10.0</cryptomator.cryptofs.version>
|
<cryptomator.cryptofs.version>2.10.0-beta2</cryptomator.cryptofs.version>
|
||||||
<cryptomator.cryptolib.version>2.2.2</cryptomator.cryptolib.version>
|
|
||||||
<cryptomator.integrations.version>1.8.0-beta1</cryptomator.integrations.version>
|
<cryptomator.integrations.version>1.8.0-beta1</cryptomator.integrations.version>
|
||||||
<cryptomator.integrations.win.version>1.6.0</cryptomator.integrations.win.version>
|
<cryptomator.integrations.win.version>1.5.1</cryptomator.integrations.win.version>
|
||||||
<cryptomator.integrations.mac.version>1.5.0-beta3</cryptomator.integrations.mac.version>
|
<cryptomator.integrations.mac.version>1.5.0-beta1</cryptomator.integrations.mac.version>
|
||||||
<cryptomator.integrations.linux.version>1.7.0-beta4</cryptomator.integrations.linux.version>
|
<cryptomator.integrations.linux.version>1.7.0-beta1</cryptomator.integrations.linux.version>
|
||||||
<cryptomator.fuse.version>6.0.1</cryptomator.fuse.version>
|
<cryptomator.fuse.version>5.1.0</cryptomator.fuse.version>
|
||||||
<cryptomator.webdav.version>3.0.1</cryptomator.webdav.version>
|
<cryptomator.webdav.version>3.0.0</cryptomator.webdav.version>
|
||||||
<cryptomator.webdav-servlet.version>1.2.12</cryptomator.webdav-servlet.version>
|
|
||||||
|
|
||||||
<!-- 3rd party dependencies -->
|
<!-- 3rd party dependencies -->
|
||||||
<caffeine.version>3.2.3</caffeine.version>
|
<commons-lang3.version>3.19.0</commons-lang3.version>
|
||||||
<commons-lang3.version>3.20.0</commons-lang3.version>
|
<dagger.version>2.57.2</dagger.version>
|
||||||
<dagger.version>2.59.2</dagger.version>
|
|
||||||
<easybind.version>2.2</easybind.version>
|
<easybind.version>2.2</easybind.version>
|
||||||
<jackson.version>2.21.1</jackson.version>
|
<jackson.version>2.20.0</jackson.version>
|
||||||
<javafx.version>25.0.2</javafx.version>
|
<javafx.version>25</javafx.version>
|
||||||
<jwt.version>4.5.1</jwt.version>
|
<jwt.version>4.5.0</jwt.version>
|
||||||
<nimbus-jose.version>10.5</nimbus-jose.version>
|
<nimbus-jose.version>10.5</nimbus-jose.version>
|
||||||
<logback.version>1.5.32</logback.version>
|
<logback.version>1.5.19</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>6.0.3</junit.jupiter.version>
|
<junit.jupiter.version>5.13.4</junit.jupiter.version>
|
||||||
<mockito.version>5.22.0</mockito.version>
|
<mockito.version>5.20.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.1.0</jetbrains.annotations.version>
|
<jetbrains.annotations.version>26.0.2-1</jetbrains.annotations.version>
|
||||||
<dependency-check.version>12.2.0</dependency-check.version>
|
<dependency-check.version>12.1.5</dependency-check.version>
|
||||||
<jacoco.version>0.8.14</jacoco.version>
|
<jacoco.version>0.8.14</jacoco.version>
|
||||||
<license-generator.version>2.7.1</license-generator.version>
|
<license-generator.version>2.7.0</license-generator.version>
|
||||||
<junit-tree-reporter.version>1.5.1</junit-tree-reporter.version>
|
<junit-tree-reporter.version>1.4.0</junit-tree-reporter.version>
|
||||||
<mvn-compiler.version>3.15.0</mvn-compiler.version>
|
<mvn-compiler.version>3.14.1</mvn-compiler.version>
|
||||||
<mvn-resources.version>3.5.0</mvn-resources.version>
|
<mvn-resources.version>3.3.1</mvn-resources.version>
|
||||||
<mvn-dependency.version>3.10.0</mvn-dependency.version>
|
<mvn-dependency.version>3.8.1</mvn-dependency.version>
|
||||||
<mvn-surefire.version>3.5.3</mvn-surefire.version>
|
<mvn-surefire.version>3.5.4</mvn-surefire.version>
|
||||||
<mvn-jar.version>3.5.0</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>
|
||||||
@@ -94,15 +91,10 @@
|
|||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<!-- Cryptomator Libs -->
|
<!-- Cryptomator Libs -->
|
||||||
<dependency>
|
|
||||||
<groupId>org.cryptomator</groupId>
|
|
||||||
<artifactId>webdav-nio-adapter-servlet</artifactId>
|
|
||||||
<version>${cryptomator.webdav-servlet.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.cryptomator</groupId>
|
<groupId>org.cryptomator</groupId>
|
||||||
<artifactId>cryptolib</artifactId>
|
<artifactId>cryptolib</artifactId>
|
||||||
<version>${cryptomator.cryptolib.version}</version>
|
<version>2.2.1</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.cryptomator</groupId>
|
<groupId>org.cryptomator</groupId>
|
||||||
@@ -236,7 +228,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.ben-manes.caffeine</groupId>
|
<groupId>com.github.ben-manes.caffeine</groupId>
|
||||||
<artifactId>caffeine</artifactId>
|
<artifactId>caffeine</artifactId>
|
||||||
<version>${caffeine.version}</version>
|
<version>3.2.2</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- JUnit / Mockito / Hamcrest -->
|
<!-- JUnit / Mockito / Hamcrest -->
|
||||||
<dependency>
|
<dependency>
|
||||||
@@ -338,6 +330,7 @@
|
|||||||
</annotationProcessorPaths>
|
</annotationProcessorPaths>
|
||||||
<compilerArgs>
|
<compilerArgs>
|
||||||
<arg>-Adagger.fastInit=enabled</arg>
|
<arg>-Adagger.fastInit=enabled</arg>
|
||||||
|
<arg>-Adagger.formatGeneratedSource=enabled</arg>
|
||||||
</compilerArgs>
|
</compilerArgs>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
|||||||
@@ -13,16 +13,12 @@ import org.cryptomator.common.locationpresets.OneDriveLinuxLocationPresetsProvid
|
|||||||
import org.cryptomator.common.locationpresets.OneDriveMacLocationPresetsProvider;
|
import org.cryptomator.common.locationpresets.OneDriveMacLocationPresetsProvider;
|
||||||
import org.cryptomator.common.locationpresets.OneDriveWindowsLocationPresetsProvider;
|
import org.cryptomator.common.locationpresets.OneDriveWindowsLocationPresetsProvider;
|
||||||
import org.cryptomator.common.locationpresets.PCloudLocationPresetsProvider;
|
import org.cryptomator.common.locationpresets.PCloudLocationPresetsProvider;
|
||||||
import org.cryptomator.integrations.revealpath.RevealPathService;
|
|
||||||
import org.cryptomator.integrations.tray.TrayMenuController;
|
import org.cryptomator.integrations.tray.TrayMenuController;
|
||||||
import org.cryptomator.integrations.uiappearance.UiAppearanceProvider;
|
|
||||||
import org.cryptomator.logging.LogbackConfiguratorFactory;
|
import org.cryptomator.logging.LogbackConfiguratorFactory;
|
||||||
import org.cryptomator.networking.SSLContextProvider;
|
import org.cryptomator.networking.SSLContextProvider;
|
||||||
import org.cryptomator.networking.SSLContextWithMacKeychain;
|
import org.cryptomator.networking.SSLContextWithMacKeychain;
|
||||||
import org.cryptomator.networking.SSLContextWithPKCS12TrustStore;
|
import org.cryptomator.networking.SSLContextWithPKCS12TrustStore;
|
||||||
import org.cryptomator.networking.SSLContextWithWindowsCertStore;
|
import org.cryptomator.networking.SSLContextWithWindowsCertStore;
|
||||||
import org.cryptomator.ui.fxapp.JfxRevealPathService;
|
|
||||||
import org.cryptomator.ui.fxapp.JfxUiAppearanceProvider;
|
|
||||||
import org.cryptomator.ui.traymenu.AwtTrayMenuController;
|
import org.cryptomator.ui.traymenu.AwtTrayMenuController;
|
||||||
|
|
||||||
open module org.cryptomator.desktop {
|
open module org.cryptomator.desktop {
|
||||||
@@ -65,8 +61,6 @@ open module org.cryptomator.desktop {
|
|||||||
uses SSLContextProvider;
|
uses SSLContextProvider;
|
||||||
uses org.cryptomator.event.NotificationHandler;
|
uses org.cryptomator.event.NotificationHandler;
|
||||||
|
|
||||||
provides UiAppearanceProvider with JfxUiAppearanceProvider;
|
|
||||||
provides RevealPathService with JfxRevealPathService;
|
|
||||||
provides TrayMenuController with AwtTrayMenuController;
|
provides TrayMenuController with AwtTrayMenuController;
|
||||||
provides Configurator with LogbackConfiguratorFactory;
|
provides Configurator with LogbackConfiguratorFactory;
|
||||||
provides SSLContextProvider with SSLContextWithWindowsCertStore, SSLContextWithMacKeychain, SSLContextWithPKCS12TrustStore;
|
provides SSLContextProvider with SSLContextWithWindowsCertStore, SSLContextWithMacKeychain, SSLContextWithPKCS12TrustStore;
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ import javax.inject.Named;
|
|||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
import java.util.concurrent.SynchronousQueue;
|
import java.util.concurrent.SynchronousQueue;
|
||||||
@@ -74,8 +76,8 @@ public abstract class CommonsModule {
|
|||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
static RevealPathService provideRevealPathService() {
|
static Optional<RevealPathService> provideRevealPathService() {
|
||||||
return RevealPathService.get().findFirst().orElseThrow();
|
return RevealPathService.get().findFirst();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package org.cryptomator.common;
|
package org.cryptomator.common;
|
||||||
|
|
||||||
import org.jetbrains.annotations.VisibleForTesting;
|
import org.jetbrains.annotations.VisibleForTesting;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
@@ -13,12 +13,10 @@ public class SubstitutingProperties extends PropertiesDecorator {
|
|||||||
private static final Pattern TEMPLATE = Pattern.compile("@\\{(\\w+)}");
|
private static final Pattern TEMPLATE = Pattern.compile("@\\{(\\w+)}");
|
||||||
|
|
||||||
private final Map<String, String> env;
|
private final Map<String, String> env;
|
||||||
private final Logger logger;
|
|
||||||
|
|
||||||
public SubstitutingProperties(Properties props, Map<String, String> systemEnvironment, Logger logger) {
|
public SubstitutingProperties(Properties props, Map<String, String> systemEnvironment) {
|
||||||
super(props);
|
super(props);
|
||||||
this.env = systemEnvironment;
|
this.env = systemEnvironment;
|
||||||
this.logger = logger;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -46,7 +44,7 @@ public class SubstitutingProperties extends PropertiesDecorator {
|
|||||||
case "localappdata" -> resolveFrom("LOCALAPPDATA", Source.ENV);
|
case "localappdata" -> resolveFrom("LOCALAPPDATA", Source.ENV);
|
||||||
case "userhome" -> resolveFrom("user.home", Source.PROPS);
|
case "userhome" -> resolveFrom("user.home", Source.PROPS);
|
||||||
default -> {
|
default -> {
|
||||||
logger.warn("Unknown variable {} in property value {}.", match.group(), value);
|
LoggerFactory.getLogger(SubstitutingProperties.class).warn("Unknown variable {} in property value {}.", match.group(), value);
|
||||||
yield match.group();
|
yield match.group();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -58,7 +56,7 @@ public class SubstitutingProperties extends PropertiesDecorator {
|
|||||||
case PROPS -> delegate.getProperty(key);
|
case PROPS -> delegate.getProperty(key);
|
||||||
};
|
};
|
||||||
if (val == null) {
|
if (val == null) {
|
||||||
logger.warn("Variable {} used for substitution not found in {}. Replaced with empty string.", key, src);
|
LoggerFactory.getLogger(SubstitutingProperties.class).warn("Variable {} used for substitution not found in {}. Replaced with empty string.", key, src);
|
||||||
return "";
|
return "";
|
||||||
} else {
|
} else {
|
||||||
return Matcher.quoteReplacement(val);
|
return Matcher.quoteReplacement(val);
|
||||||
|
|||||||
@@ -61,7 +61,6 @@ public final class MasterkeyService {
|
|||||||
Optional<Path> c9rFile = paths //
|
Optional<Path> c9rFile = paths //
|
||||||
.filter(p -> p.toString().endsWith(".c9r")) //
|
.filter(p -> p.toString().endsWith(".c9r")) //
|
||||||
.filter(p -> !p.endsWith("dir.c9r")) //
|
.filter(p -> !p.endsWith("dir.c9r")) //
|
||||||
.filter(Files::isRegularFile) //
|
|
||||||
.findFirst();
|
.findFirst();
|
||||||
if (c9rFile.isEmpty()) {
|
if (c9rFile.isEmpty()) {
|
||||||
LOG.info("Unable to detect Crypto scheme: No *.c9r file found in {}", vaultPath);
|
LOG.info("Unable to detect Crypto scheme: No *.c9r file found in {}", vaultPath);
|
||||||
|
|||||||
@@ -153,6 +153,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.keychain.SecretServiceKeychainAccess")) {
|
||||||
|
this.keychainProvider.setValue("org.cryptomator.linux.keychain.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,6 +10,14 @@ public enum UiTheme {
|
|||||||
DARK("preferences.interface.theme.dark"), //
|
DARK("preferences.interface.theme.dark"), //
|
||||||
AUTOMATIC("preferences.interface.theme.automatic");
|
AUTOMATIC("preferences.interface.theme.automatic");
|
||||||
|
|
||||||
|
public static UiTheme[] applicableValues() {
|
||||||
|
if (SystemUtils.IS_OS_MAC || SystemUtils.IS_OS_WINDOWS) {
|
||||||
|
return values();
|
||||||
|
} else {
|
||||||
|
return new UiTheme[]{LIGHT, DARK};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private final String displayName;
|
private final String displayName;
|
||||||
|
|
||||||
UiTheme(String displayName) {
|
UiTheme(String displayName) {
|
||||||
|
|||||||
@@ -1,97 +0,0 @@
|
|||||||
package org.cryptomator.launcher;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.Reader;
|
|
||||||
import java.nio.channels.Channels;
|
|
||||||
import java.nio.channels.FileChannel;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.nio.file.NoSuchFileException;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.nio.file.StandardOpenOption;
|
|
||||||
import java.util.Properties;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Factory to generate admin properties.
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* Admin properties are {@link Properties} using system properties as defaults, but allow overwriting a specific set of properties with an external config file.
|
|
||||||
* Those properties are created by calling {@link #create()}. The method first reads system property {@value #ADMIN_PROP_FILE_KEY}. If it contains a path to a valid properties file, all overridable properties from the file are loaded into the returned admin properties.
|
|
||||||
* <p>
|
|
||||||
* The overridable properties are:
|
|
||||||
* <ul>
|
|
||||||
* <li>cryptomator.logDir</li>
|
|
||||||
* <li>cryptomator.pluginDir</li>
|
|
||||||
* <li>cryptomator.p12Path</li>
|
|
||||||
* <li>cryptomator.mountPointsDir</li>
|
|
||||||
* <li>cryptomator.disableUpdateCheck</li>
|
|
||||||
* </ul>
|
|
||||||
*
|
|
||||||
* @see Properties
|
|
||||||
* @see System#getProperties()
|
|
||||||
*/
|
|
||||||
class AdminPropertiesFactory {
|
|
||||||
|
|
||||||
private static final Logger LOG = EventualLogger.INSTANCE;
|
|
||||||
private static final long MAX_CONFIG_SIZE_BYTES = 8192;
|
|
||||||
private static final String ADMIN_PROP_FILE_KEY = "cryptomator.adminConfigPath";
|
|
||||||
private static final Set<String> ALLOWED_OVERRIDES = Set.of( //
|
|
||||||
"cryptomator.logDir", //
|
|
||||||
"cryptomator.pluginDir", //
|
|
||||||
"cryptomator.p12Path", //
|
|
||||||
"cryptomator.mountPointsDir", //
|
|
||||||
"cryptomator.disableUpdateCheck");
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates new {@link Properties} containing overridable properties from the admin config.
|
|
||||||
* <p>
|
|
||||||
* The returned properties object uses as default the {@link System} properties.
|
|
||||||
* For a list of overridable properties, see {@link AdminPropertiesFactory}
|
|
||||||
*
|
|
||||||
* @return {@link Properties} containing overridable properties from the admin config and defaulting to system properties.
|
|
||||||
*/
|
|
||||||
static Properties create() {
|
|
||||||
var systemProps = System.getProperties();
|
|
||||||
var adminProps = new Properties(systemProps);
|
|
||||||
|
|
||||||
final String adminCfgPath = System.getProperty(ADMIN_PROP_FILE_KEY);
|
|
||||||
if (adminCfgPath == null) {
|
|
||||||
LOG.debug("Admin config property is not defined. Skipping.");
|
|
||||||
return adminProps;
|
|
||||||
}
|
|
||||||
var propsFromFile = loadPropertiesFromFile(Path.of(adminCfgPath));
|
|
||||||
|
|
||||||
for (var key : propsFromFile.stringPropertyNames()) {
|
|
||||||
if (ALLOWED_OVERRIDES.contains(key)) {
|
|
||||||
var value = propsFromFile.getProperty(key);
|
|
||||||
LOG.info("Overwriting {} with value {} from admin config.", key, value);
|
|
||||||
adminProps.setProperty(key, value);
|
|
||||||
} else {
|
|
||||||
LOG.debug("Property {} in admin config is not supported for override.", key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return adminProps;
|
|
||||||
}
|
|
||||||
|
|
||||||
//visible for testing
|
|
||||||
static Properties loadPropertiesFromFile(Path adminPropertiesPath) {
|
|
||||||
var adminProps = new Properties();
|
|
||||||
try (FileChannel ch = FileChannel.open(adminPropertiesPath, StandardOpenOption.READ); //
|
|
||||||
Reader reader = Channels.newReader(ch, StandardCharsets.UTF_8)) {
|
|
||||||
if (ch.size() > MAX_CONFIG_SIZE_BYTES) {
|
|
||||||
throw new IOException("Config file %s exceeds maximum size of %d".formatted(adminPropertiesPath, MAX_CONFIG_SIZE_BYTES));
|
|
||||||
}
|
|
||||||
adminProps.load(reader);
|
|
||||||
} catch (NoSuchFileException _) {
|
|
||||||
//NO-OP
|
|
||||||
LOG.debug("No admin properties found at {}.", adminPropertiesPath);
|
|
||||||
} catch (IOException | IllegalArgumentException e) {
|
|
||||||
LOG.warn("Failed to read administrative properties from {}. Returning empty properties.", adminPropertiesPath, e);
|
|
||||||
}
|
|
||||||
return adminProps;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -11,9 +11,9 @@ import org.apache.commons.lang3.SystemUtils;
|
|||||||
import org.cryptomator.common.Environment;
|
import org.cryptomator.common.Environment;
|
||||||
import org.cryptomator.common.ShutdownHook;
|
import org.cryptomator.common.ShutdownHook;
|
||||||
import org.cryptomator.common.SubstitutingProperties;
|
import org.cryptomator.common.SubstitutingProperties;
|
||||||
|
import org.cryptomator.networking.SSLContextProvider;
|
||||||
import org.cryptomator.ipc.IpcCommunicator;
|
import org.cryptomator.ipc.IpcCommunicator;
|
||||||
import org.cryptomator.logging.DebugMode;
|
import org.cryptomator.logging.DebugMode;
|
||||||
import org.cryptomator.networking.SSLContextProvider;
|
|
||||||
import org.cryptomator.ui.fxapp.FxApplicationComponent;
|
import org.cryptomator.ui.fxapp.FxApplicationComponent;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -35,8 +35,7 @@ public class Cryptomator {
|
|||||||
private static final long STARTUP_TIME = System.currentTimeMillis();
|
private static final long STARTUP_TIME = System.currentTimeMillis();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
var adminProps = AdminPropertiesFactory.create();
|
var lazyProcessedProps = new SubstitutingProperties(System.getProperties(), System.getenv());
|
||||||
var lazyProcessedProps = new SubstitutingProperties(adminProps, System.getenv(), EventualLogger.INSTANCE);
|
|
||||||
System.setProperties(lazyProcessedProps);
|
System.setProperties(lazyProcessedProps);
|
||||||
CRYPTOMATOR_COMPONENT = DaggerCryptomatorComponent.factory().create(STARTUP_TIME);
|
CRYPTOMATOR_COMPONENT = DaggerCryptomatorComponent.factory().create(STARTUP_TIME);
|
||||||
LOG = LoggerFactory.getLogger(Cryptomator.class);
|
LOG = LoggerFactory.getLogger(Cryptomator.class);
|
||||||
@@ -90,11 +89,10 @@ public class Cryptomator {
|
|||||||
* @return Nonzero exit code in case of an error.
|
* @return Nonzero exit code in case of an error.
|
||||||
*/
|
*/
|
||||||
private int run(String[] args) {
|
private int run(String[] args) {
|
||||||
debugMode.initialize();
|
|
||||||
EventualLogger.INSTANCE.drainTo(LOG);
|
|
||||||
env.log();
|
env.log();
|
||||||
LOG.debug("Dagger graph initialized after {}ms", System.currentTimeMillis() - STARTUP_TIME);
|
LOG.debug("Dagger graph initialized after {}ms", System.currentTimeMillis() - STARTUP_TIME);
|
||||||
LOG.info("Starting Cryptomator {} on {} {} ({})", env.getAppVersion(), SystemUtils.OS_NAME, SystemUtils.OS_VERSION, SystemUtils.OS_ARCH);
|
LOG.info("Starting Cryptomator {} on {} {} ({})", env.getAppVersion(), SystemUtils.OS_NAME, SystemUtils.OS_VERSION, SystemUtils.OS_ARCH);
|
||||||
|
debugMode.initialize();
|
||||||
supportedLanguages.applyPreferred();
|
supportedLanguages.applyPreferred();
|
||||||
changeDefaultSSLContext();
|
changeDefaultSSLContext();
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import dagger.Module;
|
|||||||
import dagger.Provides;
|
import dagger.Provides;
|
||||||
import org.cryptomator.integrations.autostart.AutoStartProvider;
|
import org.cryptomator.integrations.autostart.AutoStartProvider;
|
||||||
import org.cryptomator.integrations.tray.TrayIntegrationProvider;
|
import org.cryptomator.integrations.tray.TrayIntegrationProvider;
|
||||||
|
import org.cryptomator.integrations.uiappearance.UiAppearanceProvider;
|
||||||
import org.cryptomator.ui.fxapp.FxApplicationComponent;
|
import org.cryptomator.ui.fxapp.FxApplicationComponent;
|
||||||
|
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
@@ -29,6 +30,11 @@ class CryptomatorModule {
|
|||||||
return new ArrayBlockingQueue<>(10);
|
return new ArrayBlockingQueue<>(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
static Optional<UiAppearanceProvider> provideAppearanceProvider() {
|
||||||
|
return UiAppearanceProvider.get();
|
||||||
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
|
|||||||
@@ -1,106 +0,0 @@
|
|||||||
package org.cryptomator.launcher;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.Marker;
|
|
||||||
import org.slf4j.event.DefaultLoggingEvent;
|
|
||||||
import org.slf4j.event.Level;
|
|
||||||
import org.slf4j.event.LoggingEvent;
|
|
||||||
import org.slf4j.helpers.AbstractLogger;
|
|
||||||
|
|
||||||
import java.util.ArrayDeque;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Queue;
|
|
||||||
|
|
||||||
class EventualLogger extends AbstractLogger {
|
|
||||||
|
|
||||||
static final EventualLogger INSTANCE = new EventualLogger();
|
|
||||||
|
|
||||||
private final Queue<LoggingEvent> bufferedEvents = new ArrayDeque<>();
|
|
||||||
|
|
||||||
private EventualLogger() {
|
|
||||||
}
|
|
||||||
|
|
||||||
synchronized void drainTo(Logger gutter) {
|
|
||||||
for (var event : bufferedEvents) {
|
|
||||||
var builder = gutter.atLevel(event.getLevel()) //
|
|
||||||
.setCause(event.getThrowable()) //
|
|
||||||
.setMessage(event.getMessage());
|
|
||||||
Objects.requireNonNullElse(event.getArguments(), List.of()).forEach(builder::addArgument);
|
|
||||||
Objects.requireNonNullElse(event.getMarkers(), List.<Marker>of()).forEach(builder::addMarker);
|
|
||||||
builder.log();
|
|
||||||
}
|
|
||||||
bufferedEvents.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected synchronized void handleNormalizedLoggingCall(Level level, Marker marker, String messagePattern, Object[] arguments, Throwable throwable) {
|
|
||||||
var event = new DefaultLoggingEvent(level, this);
|
|
||||||
if (marker != null) {
|
|
||||||
event.addMarker(marker);
|
|
||||||
}
|
|
||||||
event.setMessage(messagePattern);
|
|
||||||
for (var arg : Objects.requireNonNullElse(arguments, new Object[]{})) {
|
|
||||||
event.addArgument(arg);
|
|
||||||
}
|
|
||||||
event.setThrowable(throwable);
|
|
||||||
bufferedEvents.add(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Unclear, unused and undocumented method of slf4j, see also https://github.com/qos-ch/slf4j/discussions/348
|
|
||||||
@Override
|
|
||||||
protected String getFullyQualifiedCallerName() {
|
|
||||||
return getClass().getCanonicalName();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isTraceEnabled() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isTraceEnabled(Marker marker) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isDebugEnabled() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isDebugEnabled(Marker marker) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isInfoEnabled() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isInfoEnabled(Marker marker) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isWarnEnabled() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isWarnEnabled(Marker marker) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isErrorEnabled() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isErrorEnabled(Marker marker) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -18,7 +18,7 @@ abstract class SSLContextDifferentTrustStoreBase implements SSLContextProvider {
|
|||||||
public SSLContext getContext(SecureRandom csprng) throws SSLContextBuildException {
|
public SSLContext getContext(SecureRandom csprng) throws SSLContextBuildException {
|
||||||
try {
|
try {
|
||||||
KeyStore truststore = getTruststore();
|
KeyStore truststore = getTruststore();
|
||||||
ensureLoaded(truststore);
|
truststore.load(null, null);
|
||||||
|
|
||||||
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
|
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
|
||||||
tmf.init(truststore);
|
tmf.init(truststore);
|
||||||
@@ -30,13 +30,4 @@ abstract class SSLContextDifferentTrustStoreBase implements SSLContextProvider {
|
|||||||
throw new SSLContextBuildException(e);
|
throw new SSLContextBuildException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ensureLoaded(KeyStore truststore) throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException {
|
|
||||||
try {
|
|
||||||
truststore.aliases();
|
|
||||||
} catch (KeyStoreException e) {
|
|
||||||
// Not initialized yet (e.g. custom KeyStore SPI); initialize without replacing preloaded stores.
|
|
||||||
truststore.load(null, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,73 +1,21 @@
|
|||||||
package org.cryptomator.networking;
|
package org.cryptomator.networking;
|
||||||
|
|
||||||
import org.cryptomator.common.Nullable;
|
|
||||||
import org.cryptomator.integrations.common.OperatingSystem;
|
import org.cryptomator.integrations.common.OperatingSystem;
|
||||||
import org.jetbrains.annotations.VisibleForTesting;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.security.KeyStore;
|
import java.security.KeyStore;
|
||||||
import java.security.KeyStoreException;
|
import java.security.KeyStoreException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
|
||||||
import java.security.Provider;
|
|
||||||
import java.security.cert.CertificateException;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Properties;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SSLContextProvider for Windows using the Windows certificate store as trust store and the bundled JDK cacerts as fallback
|
* SSLContextProvider for Windows using the Windows certificate store as trust store
|
||||||
* <p>
|
* <p>
|
||||||
* In order to work, the jdk.crypto.mscapi jmod is needed
|
* In order to work, the jdk.crypto.mscapi jmod is needed
|
||||||
*/
|
*/
|
||||||
@OperatingSystem(OperatingSystem.Value.WINDOWS)
|
@OperatingSystem(OperatingSystem.Value.WINDOWS)
|
||||||
public class SSLContextWithWindowsCertStore extends SSLContextDifferentTrustStoreBase implements SSLContextProvider {
|
public class SSLContextWithWindowsCertStore extends SSLContextDifferentTrustStoreBase implements SSLContextProvider {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(SSLContextWithWindowsCertStore.class);
|
|
||||||
private static final String DEFAULT_TRUSTSTORE_PASSWORD = "changeit"; //default JDK cacerts password
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
KeyStore getTruststore() throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException {
|
KeyStore getTruststore() throws KeyStoreException {
|
||||||
var windowsKeyStore = KeyStore.getInstance("WINDOWS-ROOT");
|
return KeyStore.getInstance("WINDOWS-ROOT");
|
||||||
var jdkKeyStore = getShippedCaCertsStore();
|
|
||||||
if (jdkKeyStore == null) {
|
|
||||||
return windowsKeyStore;
|
|
||||||
}
|
|
||||||
|
|
||||||
ensureLoaded(windowsKeyStore);
|
|
||||||
ensureLoaded(jdkKeyStore);
|
|
||||||
try {
|
|
||||||
CombinedKeyStoreSpi spi = CombinedKeyStoreSpi.create(windowsKeyStore, jdkKeyStore);
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
KeyStore getShippedCaCertsStore() {
|
|
||||||
return getCaCertsStoreByProperties(System.getProperties());
|
|
||||||
}
|
|
||||||
|
|
||||||
//for testability
|
|
||||||
@VisibleForTesting
|
|
||||||
@Nullable
|
|
||||||
KeyStore getCaCertsStoreByProperties(Properties props) {
|
|
||||||
var javaHome = Path.of(props.getProperty("java.home"));
|
|
||||||
var trustStorePassword = props.getProperty("javax.net.ssl.trustStorePassword", DEFAULT_TRUSTSTORE_PASSWORD).toCharArray();
|
|
||||||
for (var candidate : List.of(javaHome.resolve("lib/security/cacerts"), javaHome.resolve("conf/security/cacerts"))) {
|
|
||||||
try {
|
|
||||||
if (Files.isRegularFile(candidate)) {
|
|
||||||
return KeyStore.getInstance(candidate.toFile(), trustStorePassword);
|
|
||||||
}
|
|
||||||
} catch (CertificateException | KeyStoreException | IOException | NoSuchAlgorithmException e) {
|
|
||||||
LOG.info("Unable to load fallback cacerts {} file. Skipping fallback.", candidate, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ public class ChooseExistingVaultController implements FxController {
|
|||||||
this.vault = vault;
|
this.vault = vault;
|
||||||
this.vaultListManager = vaultListManager;
|
this.vaultListManager = vaultListManager;
|
||||||
this.resourceBundle = resourceBundle;
|
this.resourceBundle = resourceBundle;
|
||||||
this.screenshot = applicationStyle.appliedAppThemeProperty().map(this::selectScreenshot);
|
this.screenshot = applicationStyle.appliedThemeProperty().map(this::selectScreenshot);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Image selectScreenshot(Theme theme) {
|
private Image selectScreenshot(Theme theme) {
|
||||||
|
|||||||
@@ -1,16 +1,17 @@
|
|||||||
package org.cryptomator.ui.common;
|
package org.cryptomator.ui.common;
|
||||||
|
|
||||||
|
import dagger.Lazy;
|
||||||
import org.cryptomator.common.vaults.Vault;
|
import org.cryptomator.common.vaults.Vault;
|
||||||
import org.cryptomator.common.vaults.VaultState;
|
import org.cryptomator.common.vaults.VaultState;
|
||||||
import org.cryptomator.integrations.mount.Mountpoint;
|
import org.cryptomator.integrations.mount.Mountpoint;
|
||||||
import org.cryptomator.integrations.mount.UnmountFailedException;
|
import org.cryptomator.integrations.mount.UnmountFailedException;
|
||||||
import org.cryptomator.integrations.revealpath.RevealFailedException;
|
|
||||||
import org.cryptomator.integrations.revealpath.RevealPathService;
|
|
||||||
import org.cryptomator.ui.fxapp.FxApplicationScoped;
|
import org.cryptomator.ui.fxapp.FxApplicationScoped;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
import javafx.application.Application;
|
||||||
|
import javafx.application.HostServices;
|
||||||
import javafx.concurrent.Task;
|
import javafx.concurrent.Task;
|
||||||
import javafx.stage.Stage;
|
import javafx.stage.Stage;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -27,12 +28,12 @@ public class VaultService {
|
|||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(VaultService.class);
|
private static final Logger LOG = LoggerFactory.getLogger(VaultService.class);
|
||||||
|
|
||||||
private final RevealPathService revealPathService;
|
private final Lazy<Application> application;
|
||||||
private final ExecutorService executorService;
|
private final ExecutorService executorService;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public VaultService(RevealPathService revealPathService, ExecutorService executorService) {
|
public VaultService(Lazy<Application> application, ExecutorService executorService) {
|
||||||
this.revealPathService = revealPathService;
|
this.application = application;
|
||||||
this.executorService = executorService;
|
this.executorService = executorService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,9 +47,9 @@ public class VaultService {
|
|||||||
* @param vault The vault to reveal
|
* @param vault The vault to reveal
|
||||||
*/
|
*/
|
||||||
public Task<Vault> createRevealTask(Vault vault) {
|
public Task<Vault> createRevealTask(Vault vault) {
|
||||||
Task<Vault> task = new RevealVaultTask(vault, revealPathService);
|
Task<Vault> task = new RevealVaultTask(vault, application.get().getHostServices());
|
||||||
task.setOnSucceeded(_ -> LOG.info("Revealed {}", vault.getDisplayName()));
|
task.setOnSucceeded(evt -> LOG.info("Revealed {}", vault.getDisplayName()));
|
||||||
task.setOnFailed(evt -> LOG.warn("Failed to reveal {}", vault.getDisplayName(), evt.getSource().getException()));
|
task.setOnFailed(evt -> LOG.error("Failed to reveal " + vault.getDisplayName(), evt.getSource().getException()));
|
||||||
return task;
|
return task;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,18 +110,19 @@ public class VaultService {
|
|||||||
private static class RevealVaultTask extends Task<Vault> {
|
private static class RevealVaultTask extends Task<Vault> {
|
||||||
|
|
||||||
private final Vault vault;
|
private final Vault vault;
|
||||||
private final RevealPathService rs;
|
private final HostServices hostServices;
|
||||||
|
|
||||||
public RevealVaultTask(Vault vault, RevealPathService revealPathService) {
|
public RevealVaultTask(Vault vault, HostServices hostServices) {
|
||||||
this.vault = vault;
|
this.vault = vault;
|
||||||
this.rs = revealPathService;
|
this.hostServices = hostServices;
|
||||||
|
setOnFailed(evt -> LOG.error("Failed to reveal " + vault.getDisplayName(), getException()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Vault call() throws RevealFailedException {
|
protected Vault call() {
|
||||||
switch (vault.getMountPoint()) {
|
switch (vault.getMountPoint()) {
|
||||||
case null -> LOG.warn("Not currently mounted");
|
case null -> LOG.warn("Not currently mounted");
|
||||||
case Mountpoint.WithPath m -> rs.reveal(m.path());
|
case Mountpoint.WithPath m -> hostServices.showDocument(m.uri().toString());
|
||||||
case Mountpoint.WithUri m -> LOG.info("Vault mounted at {}", m.uri()); // TODO show in UI?
|
case Mountpoint.WithUri m -> LOG.info("Vault mounted at {}", m.uri()); // TODO show in UI?
|
||||||
}
|
}
|
||||||
return vault;
|
return vault;
|
||||||
|
|||||||
+12
-22
@@ -4,27 +4,24 @@ import javafx.beans.property.BooleanProperty;
|
|||||||
import javafx.beans.property.SimpleBooleanProperty;
|
import javafx.beans.property.SimpleBooleanProperty;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.geometry.Pos;
|
import javafx.geometry.Pos;
|
||||||
import javafx.scene.AccessibleRole;
|
|
||||||
import javafx.scene.control.Button;
|
import javafx.scene.control.Button;
|
||||||
import javafx.scene.control.ContentDisplay;
|
|
||||||
import javafx.scene.control.Label;
|
import javafx.scene.control.Label;
|
||||||
import javafx.scene.layout.HBox;
|
import javafx.scene.layout.HBox;
|
||||||
import javafx.scene.layout.Region;
|
import javafx.scene.layout.Region;
|
||||||
import javafx.scene.layout.VBox;
|
import javafx.scene.layout.VBox;
|
||||||
import java.util.ResourceBundle;
|
|
||||||
|
|
||||||
public class InfoBar extends HBox {
|
public class NotificationBar extends HBox {
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private Label infoMessage;
|
private Label notificationLabel;
|
||||||
|
|
||||||
private final BooleanProperty dismissable = new SimpleBooleanProperty();
|
private final BooleanProperty dismissable = new SimpleBooleanProperty();
|
||||||
private final BooleanProperty notify = new SimpleBooleanProperty();
|
private final BooleanProperty notify = new SimpleBooleanProperty();
|
||||||
|
|
||||||
|
|
||||||
public InfoBar() {
|
public NotificationBar() {
|
||||||
setAlignment(Pos.CENTER);
|
setAlignment(Pos.CENTER);
|
||||||
getStyleClass().addAll("info-bar");
|
setStyle("-fx-alignment: center;");
|
||||||
|
|
||||||
Region spacer = new Region();
|
Region spacer = new Region();
|
||||||
spacer.setMinWidth(40);
|
spacer.setMinWidth(40);
|
||||||
@@ -39,21 +36,14 @@ public class InfoBar extends HBox {
|
|||||||
vbox.setAlignment(Pos.CENTER);
|
vbox.setAlignment(Pos.CENTER);
|
||||||
HBox.setHgrow(vbox, javafx.scene.layout.Priority.ALWAYS);
|
HBox.setHgrow(vbox, javafx.scene.layout.Priority.ALWAYS);
|
||||||
|
|
||||||
infoMessage = new Label();
|
notificationLabel = new Label();
|
||||||
infoMessage.setFocusTraversable(true);
|
notificationLabel.getStyleClass().add("notification-label");
|
||||||
infoMessage.setAccessibleRole(AccessibleRole.BUTTON);
|
notificationLabel.setStyle("-fx-alignment: center;");
|
||||||
vbox.getChildren().add(infoMessage);
|
vbox.getChildren().add(notificationLabel);
|
||||||
|
|
||||||
var closeGraphic = new FontAwesome5IconView();
|
Button closeButton = new Button("X");
|
||||||
closeGraphic.setGlyph(FontAwesome5Icon.TIMES);
|
|
||||||
closeGraphic.setGlyphSize(12);
|
|
||||||
closeGraphic.getStyleClass().add("glyph");
|
|
||||||
|
|
||||||
Button closeButton = new Button();
|
|
||||||
closeButton.setGraphic(closeGraphic);
|
|
||||||
closeButton.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
|
|
||||||
closeButton.setAccessibleText(ResourceBundle.getBundle("i18n.strings").getString("main.notification.closeButton.tooltip"));
|
|
||||||
closeButton.setMinWidth(40);
|
closeButton.setMinWidth(40);
|
||||||
|
closeButton.setStyle("-fx-background-color: transparent; -fx-text-fill: white; -fx-font-weight: bold;");
|
||||||
closeButton.visibleProperty().bind(dismissable);
|
closeButton.visibleProperty().bind(dismissable);
|
||||||
|
|
||||||
closeButton.setOnAction(_ -> {
|
closeButton.setOnAction(_ -> {
|
||||||
@@ -71,11 +61,11 @@ public class InfoBar extends HBox {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String getText() {
|
public String getText() {
|
||||||
return infoMessage.getText();
|
return notificationLabel.getText();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setText(String text) {
|
public void setText(String text) {
|
||||||
infoMessage.setText(text);
|
notificationLabel.setText(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setStyleClass(String styleClass) {
|
public void setStyleClass(String styleClass) {
|
||||||
@@ -61,15 +61,6 @@ public class Dialogs {
|
|||||||
.setOkButtonKey(BUTTON_KEY_CLOSE);
|
.setOkButtonKey(BUTTON_KEY_CLOSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SimpleDialog.Builder prepareHubVaultArchived(Stage window, Vault vault) {
|
|
||||||
return createDialogBuilder().setOwner(window) //
|
|
||||||
.setTitleKey("unlock.title", vault.getDisplayName()) //
|
|
||||||
.setMessageKey("hub.archived.message") //
|
|
||||||
.setDescriptionKey("hub.archived.description") //
|
|
||||||
.setIcon(FontAwesome5Icon.BAN)//
|
|
||||||
.setOkButtonKey(BUTTON_KEY_CLOSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
public SimpleDialog.Builder prepareRecoveryVaultAdded(Stage window, String displayName) {
|
public SimpleDialog.Builder prepareRecoveryVaultAdded(Stage window, String displayName) {
|
||||||
return createDialogBuilder().setOwner(window) //
|
return createDialogBuilder().setOwner(window) //
|
||||||
.setTitleKey("recover.existing.title") //
|
.setTitleKey("recover.existing.title") //
|
||||||
|
|||||||
@@ -2,17 +2,18 @@ package org.cryptomator.ui.eventview;
|
|||||||
|
|
||||||
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.cryptofs.event.FileIsInUseEvent;
|
||||||
|
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.event.BrokenDirFileEvent;
|
import org.cryptomator.cryptofs.event.BrokenDirFileEvent;
|
||||||
import org.cryptomator.cryptofs.event.BrokenFileNodeEvent;
|
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.cryptofs.event.FileIsInUseEvent;
|
|
||||||
import org.cryptomator.event.FSEventBucket;
|
|
||||||
import org.cryptomator.event.FSEventBucketContent;
|
|
||||||
import org.cryptomator.event.FileSystemEventAggregator;
|
|
||||||
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;
|
||||||
@@ -45,6 +46,7 @@ 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.Map;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.ResourceBundle;
|
import java.util.ResourceBundle;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
@@ -55,6 +57,7 @@ public class EventListCellController implements FxController {
|
|||||||
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 FileSystemEventAggregator fileSystemEventAggregator;
|
private final FileSystemEventAggregator fileSystemEventAggregator;
|
||||||
|
@Nullable
|
||||||
private final RevealPathService revealService;
|
private final RevealPathService revealService;
|
||||||
private final ResourceBundle resourceBundle;
|
private final ResourceBundle resourceBundle;
|
||||||
private final ObjectProperty<Map.Entry<FSEventBucket, FSEventBucketContent>> eventEntry;
|
private final ObjectProperty<Map.Entry<FSEventBucket, FSEventBucketContent>> eventEntry;
|
||||||
@@ -79,17 +82,15 @@ public class EventListCellController implements FxController {
|
|||||||
Button eventActionsButton;
|
Button eventActionsButton;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public EventListCellController(FileSystemEventAggregator fileSystemEventAggregator,
|
public EventListCellController(FileSystemEventAggregator fileSystemEventAggregator, Optional<RevealPathService> revealService, ResourceBundle resourceBundle) {
|
||||||
RevealPathService revealService,
|
|
||||||
ResourceBundle resourceBundle) {
|
|
||||||
this.fileSystemEventAggregator = fileSystemEventAggregator;
|
this.fileSystemEventAggregator = fileSystemEventAggregator;
|
||||||
this.revealService = revealService;
|
this.revealService = revealService.orElseGet(() -> null);
|
||||||
this.resourceBundle = resourceBundle;
|
this.resourceBundle = resourceBundle;
|
||||||
this.eventEntry = 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(eventEntry, e -> e.getValue().count() == 1 ? "" : "(" + e.getValue().count() + ")", "");
|
this.eventCount = ObservableUtil.mapWithDefault(eventEntry, e -> e.getValue().count() == 1? "" : "("+ e.getValue().count() +")", "");
|
||||||
this.vaultUnlocked = ObservableUtil.mapWithDefault(eventEntry.flatMap(e -> e.getKey().vault().unlockedProperty()), Function.identity(), false);
|
this.vaultUnlocked = ObservableUtil.mapWithDefault(eventEntry.flatMap(e -> e.getKey().vault().unlockedProperty()), Function.identity(), false);
|
||||||
this.readableTime = ObservableUtil.mapWithDefault(eventEntry, e -> LOCAL_TIME_FORMATTER.format(e.getValue().mostRecentEvent().getTimestamp()), "");
|
this.readableTime = ObservableUtil.mapWithDefault(eventEntry, e -> LOCAL_TIME_FORMATTER.format(e.getValue().mostRecentEvent().getTimestamp()), "");
|
||||||
this.readableDate = ObservableUtil.mapWithDefault(eventEntry, e -> LOCAL_DATE_FORMATTER.format(e.getValue().mostRecentEvent().getTimestamp()), "");
|
this.readableDate = ObservableUtil.mapWithDefault(eventEntry, e -> LOCAL_DATE_FORMATTER.format(e.getValue().mostRecentEvent().getTimestamp()), "");
|
||||||
@@ -135,8 +136,13 @@ public class EventListCellController implements FxController {
|
|||||||
eventMessage.setValue(resourceBundle.getString("eventView.entry.inUse.message"));
|
eventMessage.setValue(resourceBundle.getString("eventView.entry.inUse.message"));
|
||||||
var indexFileName = fiiue.cleartextPath().lastIndexOf("/");
|
var indexFileName = fiiue.cleartextPath().lastIndexOf("/");
|
||||||
eventDescription.setValue(fiiue.cleartextPath().substring(indexFileName + 1));
|
eventDescription.setValue(fiiue.cleartextPath().substring(indexFileName + 1));
|
||||||
addLocalizedAction("eventView.entry.inUse.showDecrypted", () -> reveal(revealService, convertVaultPathToSystemPath(fiiue.cleartextPath())));
|
if (revealService != null) {
|
||||||
addLocalizedAction("eventView.entry.inUse.showEncrypted", () -> reveal(revealService, fiiue.ciphertextPath()));
|
addLocalizedAction("eventView.entry.inUse.showDecrypted", () -> reveal(revealService, convertVaultPathToSystemPath(fiiue.cleartextPath())));
|
||||||
|
addLocalizedAction("eventView.entry.inUse.showEncrypted", () -> reveal(revealService, fiiue.ciphertextPath()));
|
||||||
|
} else {
|
||||||
|
addLocalizedAction("eventView.entry.inUse.copyDecrypted", () -> copyToClipboard(convertVaultPathToSystemPath(fiiue.cleartextPath()).toString()));
|
||||||
|
addLocalizedAction("eventView.entry.inUse.copyEncrypted", () -> copyToClipboard(fiiue.ciphertextPath().toString()));
|
||||||
|
}
|
||||||
|
|
||||||
var userAndDevice = fiiue.owner().split(Constants.HUB_USER_DEVICE_SEPARATOR);
|
var userAndDevice = fiiue.owner().split(Constants.HUB_USER_DEVICE_SEPARATOR);
|
||||||
var user = userAndDevice[0];
|
var user = userAndDevice[0];
|
||||||
@@ -150,7 +156,11 @@ public class EventListCellController implements FxController {
|
|||||||
eventIcon.setValue(FontAwesome5Icon.TIMES);
|
eventIcon.setValue(FontAwesome5Icon.TIMES);
|
||||||
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());
|
||||||
addLocalizedAction("eventView.entry.brokenFileNode.showEncrypted", () -> reveal(revealService, bfe.ciphertextPath()));
|
if (revealService != null) {
|
||||||
|
addLocalizedAction("eventView.entry.brokenFileNode.showEncrypted", () -> reveal(revealService, bfe.ciphertextPath()));
|
||||||
|
} else {
|
||||||
|
addLocalizedAction("eventView.entry.brokenFileNode.copyEncrypted", () -> copyToClipboard(bfe.ciphertextPath().toString()));
|
||||||
|
}
|
||||||
addLocalizedAction("eventView.entry.brokenFileNode.copyDecrypted", () -> copyToClipboard(convertVaultPathToSystemPath(bfe.cleartextPath()).toString()));
|
addLocalizedAction("eventView.entry.brokenFileNode.copyDecrypted", () -> copyToClipboard(convertVaultPathToSystemPath(bfe.cleartextPath()).toString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,29 +168,46 @@ public class EventListCellController implements FxController {
|
|||||||
eventIcon.setValue(FontAwesome5Icon.CHECK);
|
eventIcon.setValue(FontAwesome5Icon.CHECK);
|
||||||
eventMessage.setValue(resourceBundle.getString("eventView.entry.conflictResolved.message"));
|
eventMessage.setValue(resourceBundle.getString("eventView.entry.conflictResolved.message"));
|
||||||
eventDescription.setValue(cre.resolvedCiphertextPath().getFileName().toString());
|
eventDescription.setValue(cre.resolvedCiphertextPath().getFileName().toString());
|
||||||
addLocalizedAction("eventView.entry.conflictResolved.showDecrypted", () -> reveal(revealService, convertVaultPathToSystemPath(cre.resolvedCleartextPath())));
|
if (revealService != null) {
|
||||||
|
addLocalizedAction("eventView.entry.conflictResolved.showDecrypted", () -> reveal(revealService, convertVaultPathToSystemPath(cre.resolvedCleartextPath())));
|
||||||
|
} else {
|
||||||
|
addLocalizedAction("eventView.entry.conflictResolved.copyDecrypted", () -> copyToClipboard(convertVaultPathToSystemPath(cre.resolvedCleartextPath()).toString()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void adjustToConflictEvent(ConflictResolutionFailedEvent cfe) {
|
private void adjustToConflictEvent(ConflictResolutionFailedEvent cfe) {
|
||||||
eventIcon.setValue(FontAwesome5Icon.COMPRESS_ALT);
|
eventIcon.setValue(FontAwesome5Icon.COMPRESS_ALT);
|
||||||
eventMessage.setValue(resourceBundle.getString("eventView.entry.conflict.message"));
|
eventMessage.setValue(resourceBundle.getString("eventView.entry.conflict.message"));
|
||||||
eventDescription.setValue(cfe.conflictingCiphertextPath().getFileName().toString());
|
eventDescription.setValue(cfe.conflictingCiphertextPath().getFileName().toString());
|
||||||
addLocalizedAction("eventView.entry.conflict.showDecrypted", () -> reveal(revealService, convertVaultPathToSystemPath(cfe.canonicalCleartextPath())));
|
if (revealService != null) {
|
||||||
addLocalizedAction("eventView.entry.conflict.showEncrypted", () -> reveal(revealService, cfe.conflictingCiphertextPath()));
|
addLocalizedAction("eventView.entry.conflict.showDecrypted", () -> reveal(revealService, convertVaultPathToSystemPath(cfe.canonicalCleartextPath())));
|
||||||
|
addLocalizedAction("eventView.entry.conflict.showEncrypted", () -> reveal(revealService, cfe.conflictingCiphertextPath()));
|
||||||
|
} else {
|
||||||
|
addLocalizedAction("eventView.entry.conflict.copyDecrypted", () -> copyToClipboard(convertVaultPathToSystemPath(cfe.canonicalCleartextPath()).toString()));
|
||||||
|
addLocalizedAction("eventView.entry.conflict.copyEncrypted", () -> copyToClipboard(cfe.conflictingCiphertextPath().toString()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void adjustToDecryptionFailedEvent(DecryptionFailedEvent dfe) {
|
private void adjustToDecryptionFailedEvent(DecryptionFailedEvent dfe) {
|
||||||
eventIcon.setValue(FontAwesome5Icon.BAN);
|
eventIcon.setValue(FontAwesome5Icon.BAN);
|
||||||
eventMessage.setValue(resourceBundle.getString("eventView.entry.decryptionFailed.message"));
|
eventMessage.setValue(resourceBundle.getString("eventView.entry.decryptionFailed.message"));
|
||||||
eventDescription.setValue(dfe.ciphertextPath().getFileName().toString());
|
eventDescription.setValue(dfe.ciphertextPath().getFileName().toString());
|
||||||
addLocalizedAction("eventView.entry.decryptionFailed.showEncrypted", () -> reveal(revealService, dfe.ciphertextPath()));
|
if (revealService != null) {
|
||||||
|
addLocalizedAction("eventView.entry.decryptionFailed.showEncrypted", () -> reveal(revealService, dfe.ciphertextPath()));
|
||||||
|
} else {
|
||||||
|
addLocalizedAction("eventView.entry.decryptionFailed.copyEncrypted", () -> copyToClipboard(dfe.ciphertextPath().toString()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void adjustToBrokenDirFileEvent(BrokenDirFileEvent bde) {
|
private void adjustToBrokenDirFileEvent(BrokenDirFileEvent bde) {
|
||||||
eventIcon.setValue(FontAwesome5Icon.TIMES);
|
eventIcon.setValue(FontAwesome5Icon.TIMES);
|
||||||
eventMessage.setValue(resourceBundle.getString("eventView.entry.brokenDirFile.message"));
|
eventMessage.setValue(resourceBundle.getString("eventView.entry.brokenDirFile.message"));
|
||||||
eventDescription.setValue(bde.ciphertextPath().getParent().getFileName().toString());
|
eventDescription.setValue(bde.ciphertextPath().getParent().getFileName().toString());
|
||||||
addLocalizedAction("eventView.entry.brokenDirFile.showEncrypted", () -> reveal(revealService, bde.ciphertextPath()));
|
if (revealService != null) {
|
||||||
|
addLocalizedAction("eventView.entry.brokenDirFile.showEncrypted", () -> reveal(revealService, bde.ciphertextPath()));
|
||||||
|
} else {
|
||||||
|
addLocalizedAction("eventView.entry.brokenDirFile.copyEncrypted", () -> copyToClipboard(bde.ciphertextPath().toString()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addLocalizedAction(String localizationKey, Runnable action) {
|
private void addLocalizedAction(String localizationKey, Runnable action) {
|
||||||
@@ -243,7 +270,7 @@ public class EventListCellController implements FxController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var mountPoint = v.getMountPoint().uri().getPath();
|
var mountPoint = v.getMountPoint().uri().getPath();
|
||||||
if (SystemUtils.IS_OS_WINDOWS) {
|
if(SystemUtils.IS_OS_WINDOWS) {
|
||||||
mountPoint = mountPoint.substring(1); //strip away any leading "/", otherwise there are errors
|
mountPoint = mountPoint.substring(1); //strip away any leading "/", otherwise there are errors
|
||||||
}
|
}
|
||||||
return Path.of(mountPoint, vaultInternalPath.substring(1)); //vaultPaths are always absolute
|
return Path.of(mountPoint, vaultInternalPath.substring(1)); //vaultPaths are always absolute
|
||||||
|
|||||||
@@ -10,20 +10,16 @@ import org.slf4j.LoggerFactory;
|
|||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
import javafx.application.Application;
|
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
|
||||||
|
|
||||||
@FxApplicationScoped
|
@FxApplicationScoped
|
||||||
public class FxApplication {
|
public class FxApplication {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(FxApplication.class);
|
private static final Logger LOG = LoggerFactory.getLogger(FxApplication.class);
|
||||||
|
|
||||||
static final AtomicReference<Application> INSTANCE = new AtomicReference<>();
|
|
||||||
|
|
||||||
private final long startupTime;
|
private final long startupTime;
|
||||||
private final Environment environment;
|
private final Environment environment;
|
||||||
private final Settings settings;
|
private final Settings settings;
|
||||||
@@ -37,8 +33,7 @@ public class FxApplication {
|
|||||||
private final FxNotificationManager notificationManager;
|
private final FxNotificationManager notificationManager;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
FxApplication(Application fxApp,
|
FxApplication(@Named("startupTime") long startupTime, //
|
||||||
@Named("startupTime") long startupTime, //
|
|
||||||
Environment environment, //
|
Environment environment, //
|
||||||
Settings settings, //
|
Settings settings, //
|
||||||
AppLaunchEventHandler launchEventHandler, //
|
AppLaunchEventHandler launchEventHandler, //
|
||||||
@@ -60,8 +55,6 @@ public class FxApplication {
|
|||||||
this.autoUnlocker = autoUnlocker;
|
this.autoUnlocker = autoUnlocker;
|
||||||
this.fxFSEventList = fxFSEventList;
|
this.fxFSEventList = fxFSEventList;
|
||||||
this.notificationManager = notificationManager;
|
this.notificationManager = notificationManager;
|
||||||
|
|
||||||
INSTANCE.set(fxApp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void start() {
|
public void start() {
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ package org.cryptomator.ui.fxapp;
|
|||||||
|
|
||||||
import dagger.Module;
|
import dagger.Module;
|
||||||
import dagger.Provides;
|
import dagger.Provides;
|
||||||
import org.cryptomator.integrations.uiappearance.UiAppearanceProvider;
|
|
||||||
import org.cryptomator.ui.decryptname.DecryptNameComponent;
|
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;
|
||||||
@@ -27,7 +26,6 @@ import org.cryptomator.ui.vaultoptions.VaultOptionsComponent;
|
|||||||
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;
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
@Module(subcomponents = {TrayMenuComponent.class, //
|
@Module(subcomponents = {TrayMenuComponent.class, //
|
||||||
DecryptNameComponent.class, //
|
DecryptNameComponent.class, //
|
||||||
@@ -43,7 +41,7 @@ import java.util.Optional;
|
|||||||
ShareVaultComponent.class, //
|
ShareVaultComponent.class, //
|
||||||
EventViewComponent.class, //
|
EventViewComponent.class, //
|
||||||
RecoveryKeyComponent.class, //
|
RecoveryKeyComponent.class, //
|
||||||
NotificationComponent.class})
|
NotificationComponent.class })
|
||||||
abstract class FxApplicationModule {
|
abstract class FxApplicationModule {
|
||||||
|
|
||||||
private static Image createImageFromResource(String resourceName) throws IOException {
|
private static Image createImageFromResource(String resourceName) throws IOException {
|
||||||
@@ -52,12 +50,6 @@ abstract class FxApplicationModule {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
|
||||||
@FxApplicationScoped
|
|
||||||
static Optional<UiAppearanceProvider> provideAppearanceProvider() {
|
|
||||||
return UiAppearanceProvider.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@FxApplicationScoped
|
@FxApplicationScoped
|
||||||
static TrayMenuComponent provideTrayMenuComponent(TrayMenuComponent.Builder builder) {
|
static TrayMenuComponent provideTrayMenuComponent(TrayMenuComponent.Builder builder) {
|
||||||
|
|||||||
@@ -36,91 +36,82 @@ public class FxApplicationStyle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void initialize() {
|
public void initialize() {
|
||||||
var uiTheme = settings.theme.get();
|
|
||||||
if (uiTheme == UiTheme.AUTOMATIC) {
|
|
||||||
registerOsThemeListener();
|
|
||||||
}
|
|
||||||
applyTheme(uiTheme);
|
|
||||||
settings.theme.addListener(this::appThemeChanged);
|
settings.theme.addListener(this::appThemeChanged);
|
||||||
|
loadSelectedStyleSheet(settings.theme.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void appThemeChanged(@SuppressWarnings("unused") ObservableValue<? extends UiTheme> observable, UiTheme oldValue, UiTheme newValue) {
|
private void appThemeChanged(@SuppressWarnings("unused") ObservableValue<? extends UiTheme> observable, @SuppressWarnings("unused") UiTheme oldValue, UiTheme newValue) {
|
||||||
if (oldValue == newValue) {
|
if (appearanceProvider.isPresent() && oldValue == UiTheme.AUTOMATIC && newValue != UiTheme.AUTOMATIC) {
|
||||||
// no-op
|
|
||||||
} else if (newValue == UiTheme.AUTOMATIC) {
|
|
||||||
registerOsThemeListener();
|
|
||||||
} else if (oldValue == UiTheme.AUTOMATIC) {
|
|
||||||
removeOsThemeListener();
|
|
||||||
}
|
|
||||||
|
|
||||||
applyTheme(newValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void removeOsThemeListener() {
|
|
||||||
if (appearanceProvider.isPresent()) {
|
|
||||||
try {
|
try {
|
||||||
appearanceProvider.get().removeListener(systemInterfaceThemeListener);
|
appearanceProvider.get().removeListener(systemInterfaceThemeListener);
|
||||||
} catch (UiAppearanceException e) {
|
} catch (UiAppearanceException e) {
|
||||||
LOG.warn("Failed to disable automatic theme switching.", e);
|
LOG.error("Failed to disable automatic theme switching.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
loadSelectedStyleSheet(newValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadSelectedStyleSheet(UiTheme desiredTheme) {
|
||||||
|
UiTheme theme = licenseHolder.isValidLicense() ? desiredTheme : UiTheme.LIGHT;
|
||||||
|
switch (theme) {
|
||||||
|
case LIGHT -> applyLightTheme();
|
||||||
|
case DARK -> applyDarkTheme();
|
||||||
|
case AUTOMATIC -> {
|
||||||
|
appearanceProvider.ifPresent(provider -> {
|
||||||
|
try {
|
||||||
|
provider.addListener(systemInterfaceThemeListener);
|
||||||
|
} catch (UiAppearanceException e) {
|
||||||
|
LOG.error("Failed to enable automatic theme switching.");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
applySystemTheme();
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
LOG.debug("Unable to remove listener os theme changes: No supported UiAppearanceProvider present");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerOsThemeListener() {
|
private void systemInterfaceThemeChanged(Theme theme) {
|
||||||
|
switch (theme) {
|
||||||
|
case LIGHT -> applyLightTheme();
|
||||||
|
case DARK -> applyDarkTheme();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void applySystemTheme() {
|
||||||
if (appearanceProvider.isPresent()) {
|
if (appearanceProvider.isPresent()) {
|
||||||
try {
|
systemInterfaceThemeChanged(appearanceProvider.get().getSystemTheme());
|
||||||
appearanceProvider.get().addListener(systemInterfaceThemeListener);
|
|
||||||
} catch (UiAppearanceException e) {
|
|
||||||
LOG.warn("Failed to enable automatic theme switching.", e);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
LOG.warn("Unable to register for os theme changes: No supported UiAppearanceProvider present");
|
LOG.warn("No UiAppearanceProvider present, assuming LIGHT theme...");
|
||||||
|
applyLightTheme();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void applyTheme(UiTheme uiTheme) {
|
private void applyLightTheme() {
|
||||||
if (!licenseHolder.isValidLicense()) {
|
var stylesheet = Optional //
|
||||||
loadAndApplyLightTheme();
|
.ofNullable(getClass().getResource("/css/light_theme.bss")) //
|
||||||
} else {
|
.orElse(getClass().getResource("/css/light_theme.css"));
|
||||||
switch (uiTheme) {
|
|
||||||
case AUTOMATIC -> {
|
|
||||||
var osTheme = appearanceProvider.map(UiAppearanceProvider::getSystemTheme).orElse(Theme.LIGHT);
|
|
||||||
systemInterfaceThemeChanged(osTheme);
|
|
||||||
}
|
|
||||||
case LIGHT -> loadAndApplyLightTheme();
|
|
||||||
case DARK -> loadAndApplyDarkTheme();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void systemInterfaceThemeChanged(Theme osTheme) {
|
|
||||||
switch (osTheme) {
|
|
||||||
case LIGHT -> loadAndApplyLightTheme();
|
|
||||||
case DARK -> loadAndApplyDarkTheme();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void loadAndApplyLightTheme() {
|
|
||||||
loadAndApplyTheme(Theme.LIGHT, "/css/light_theme.css");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void loadAndApplyDarkTheme() {
|
|
||||||
loadAndApplyTheme(Theme.DARK, "/css/dark_theme.css");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void loadAndApplyTheme(Theme appTheme, String cssFile) {
|
|
||||||
var stylesheet = getClass().getResource(cssFile);
|
|
||||||
if (stylesheet == null) {
|
if (stylesheet == null) {
|
||||||
throw new IllegalStateException("Cannot find resource %s".formatted(cssFile));
|
LOG.warn("Failed to load light_theme stylesheet");
|
||||||
|
} else {
|
||||||
|
Application.setUserAgentStylesheet(stylesheet.toString());
|
||||||
|
appearanceProvider.ifPresent(provider -> provider.adjustToTheme(Theme.LIGHT));
|
||||||
|
appliedTheme.set(Theme.LIGHT);
|
||||||
}
|
}
|
||||||
Application.setUserAgentStylesheet(stylesheet.toString());
|
|
||||||
appearanceProvider.ifPresent(provider -> provider.adjustToTheme(appTheme));
|
|
||||||
appliedTheme.set(appTheme);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ObjectProperty<Theme> appliedAppThemeProperty() {
|
private void applyDarkTheme() {
|
||||||
|
var stylesheet = Optional //
|
||||||
|
.ofNullable(getClass().getResource("/css/dark_theme.bss")) //
|
||||||
|
.orElse(getClass().getResource("/css/dark_theme.css"));
|
||||||
|
if (stylesheet == null) {
|
||||||
|
LOG.warn("Failed to load dark_theme stylesheet");
|
||||||
|
} else {
|
||||||
|
Application.setUserAgentStylesheet(stylesheet.toString());
|
||||||
|
appearanceProvider.ifPresent(provider -> provider.adjustToTheme(Theme.DARK));
|
||||||
|
appliedTheme.set(Theme.DARK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ObjectProperty<Theme> appliedThemeProperty() {
|
||||||
return appliedTheme;
|
return appliedTheme;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,6 @@ package org.cryptomator.ui.fxapp;
|
|||||||
import org.cryptomator.event.FSEventBucket;
|
import org.cryptomator.event.FSEventBucket;
|
||||||
import org.cryptomator.event.FSEventBucketContent;
|
import org.cryptomator.event.FSEventBucketContent;
|
||||||
import org.cryptomator.event.FileSystemEventAggregator;
|
import org.cryptomator.event.FileSystemEventAggregator;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
@@ -13,7 +11,6 @@ import javafx.beans.property.SimpleBooleanProperty;
|
|||||||
import javafx.collections.FXCollections;
|
import javafx.collections.FXCollections;
|
||||||
import javafx.collections.ObservableList;
|
import javafx.collections.ObservableList;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.RejectedExecutionException;
|
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
@@ -26,8 +23,6 @@ import java.util.concurrent.TimeUnit;
|
|||||||
@FxApplicationScoped
|
@FxApplicationScoped
|
||||||
public class FxFSEventList {
|
public class FxFSEventList {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(FxFSEventList.class);
|
|
||||||
|
|
||||||
private final ObservableList<Map.Entry<FSEventBucket, FSEventBucketContent>> events;
|
private final ObservableList<Map.Entry<FSEventBucket, FSEventBucketContent>> events;
|
||||||
private final FileSystemEventAggregator eventAggregator;
|
private final FileSystemEventAggregator eventAggregator;
|
||||||
private final ScheduledExecutorService scheduler;
|
private final ScheduledExecutorService scheduler;
|
||||||
@@ -42,13 +37,7 @@ public class FxFSEventList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void schedulePollForUpdates() {
|
public void schedulePollForUpdates() {
|
||||||
try {
|
scheduler.schedule(this::checkForEventUpdates, 1000, TimeUnit.MILLISECONDS);
|
||||||
scheduler.schedule(this::checkForEventUpdates, 1000, TimeUnit.MILLISECONDS);
|
|
||||||
} catch ( RejectedExecutionException e) {
|
|
||||||
if(!scheduler.isShutdown()) {
|
|
||||||
LOG.warn("Failed to poll for filesystem events", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,37 +0,0 @@
|
|||||||
package org.cryptomator.ui.fxapp;
|
|
||||||
|
|
||||||
import org.cryptomator.integrations.common.DisplayName;
|
|
||||||
import org.cryptomator.integrations.common.OperatingSystem;
|
|
||||||
import org.cryptomator.integrations.common.Priority;
|
|
||||||
import org.cryptomator.integrations.revealpath.RevealFailedException;
|
|
||||||
import org.cryptomator.integrations.revealpath.RevealPathService;
|
|
||||||
|
|
||||||
import java.nio.file.Path;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A {@link RevealPathService} service implementation using the JavaFX {@link javafx.application.HostServices#showDocument(String)} to reveal documents.
|
|
||||||
* <p>
|
|
||||||
* Internally the HostServices class uses GTK on Linux.
|
|
||||||
*
|
|
||||||
* @implNote {@link #reveal(Path)} only succeeds when the class {@link FxApplication} is initialized.
|
|
||||||
*/
|
|
||||||
@DisplayName("JavaFX HostServices (GTK)")
|
|
||||||
@OperatingSystem(OperatingSystem.Value.LINUX)
|
|
||||||
@Priority(10)
|
|
||||||
public class JfxRevealPathService implements RevealPathService {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void reveal(Path p) throws RevealFailedException {
|
|
||||||
var fxApp = FxApplication.INSTANCE.get();
|
|
||||||
if (fxApp != null) {
|
|
||||||
fxApp.getHostServices().showDocument(p.toUri().toString());
|
|
||||||
} else {
|
|
||||||
throw new RevealFailedException("JavaFX Application not initialized");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isSupported() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
package org.cryptomator.ui.fxapp;
|
|
||||||
|
|
||||||
import org.cryptomator.integrations.common.DisplayName;
|
|
||||||
import org.cryptomator.integrations.common.OperatingSystem;
|
|
||||||
import org.cryptomator.integrations.common.Priority;
|
|
||||||
import org.cryptomator.integrations.uiappearance.Theme;
|
|
||||||
import org.cryptomator.integrations.uiappearance.UiAppearanceException;
|
|
||||||
import org.cryptomator.integrations.uiappearance.UiAppearanceListener;
|
|
||||||
import org.cryptomator.integrations.uiappearance.UiAppearanceProvider;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import javafx.application.ColorScheme;
|
|
||||||
import javafx.application.Platform;
|
|
||||||
import javafx.beans.value.ChangeListener;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
|
|
||||||
@DisplayName("JavaFX Color Scheme switcher")
|
|
||||||
@OperatingSystem(OperatingSystem.Value.LINUX)
|
|
||||||
@OperatingSystem(OperatingSystem.Value.WINDOWS)
|
|
||||||
@Priority(1050)
|
|
||||||
public class JfxUiAppearanceProvider implements UiAppearanceProvider {
|
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(JfxUiAppearanceProvider.class);
|
|
||||||
|
|
||||||
private final ConcurrentHashMap<UiAppearanceListener, ChangeListener<ColorScheme>> uiAppearanceListeners = new ConcurrentHashMap<>();
|
|
||||||
private final Platform.Preferences preferences = Platform.getPreferences(); //Note: this service impl MUST be loaded in the fx application thread
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Theme getSystemTheme() {
|
|
||||||
return switch (preferences.getColorScheme()) {
|
|
||||||
case DARK -> Theme.DARK;
|
|
||||||
case LIGHT -> Theme.LIGHT;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void adjustToTheme(Theme theme) {
|
|
||||||
//no-op
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addListener(UiAppearanceListener uiAppearanceListener) throws UiAppearanceException {
|
|
||||||
var fxChangeListener = (ChangeListener<ColorScheme>) (_, _, newScheme) -> {
|
|
||||||
var newTheme = switch (newScheme) {
|
|
||||||
case DARK -> Theme.DARK;
|
|
||||||
case LIGHT -> Theme.LIGHT;
|
|
||||||
};
|
|
||||||
uiAppearanceListener.systemAppearanceChanged(newTheme);
|
|
||||||
};
|
|
||||||
LOG.debug("Register listener for OS theme changes");
|
|
||||||
uiAppearanceListeners.computeIfAbsent(uiAppearanceListener, k -> {
|
|
||||||
Platform.runLater(() -> preferences.colorSchemeProperty().addListener(fxChangeListener));
|
|
||||||
return fxChangeListener;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void removeListener(UiAppearanceListener uiAppearanceListener) throws UiAppearanceException {
|
|
||||||
var fxChangeListener = uiAppearanceListeners.remove(uiAppearanceListener);
|
|
||||||
if (fxChangeListener != null) {
|
|
||||||
LOG.debug("Removing listener for OS theme changes");
|
|
||||||
Platform.runLater(() -> preferences.colorSchemeProperty().removeListener(fxChangeListener));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@@ -4,12 +4,9 @@ import com.google.common.base.Throwables;
|
|||||||
import org.cryptomator.common.Environment;
|
import org.cryptomator.common.Environment;
|
||||||
import org.cryptomator.common.vaults.Vault;
|
import org.cryptomator.common.vaults.Vault;
|
||||||
import org.cryptomator.cryptofs.VaultConfig;
|
import org.cryptomator.cryptofs.VaultConfig;
|
||||||
import org.cryptomator.integrations.revealpath.RevealFailedException;
|
|
||||||
import org.cryptomator.integrations.revealpath.RevealPathService;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
import javafx.application.Application;
|
||||||
import java.io.BufferedWriter;
|
import java.io.BufferedWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStreamWriter;
|
import java.io.OutputStreamWriter;
|
||||||
@@ -28,7 +25,6 @@ import java.util.stream.Collectors;
|
|||||||
@HealthCheckScoped
|
@HealthCheckScoped
|
||||||
public class ReportWriter {
|
public class ReportWriter {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(ReportWriter.class);
|
|
||||||
private static final String REPORT_HEADER = """
|
private static final String REPORT_HEADER = """
|
||||||
*******************************************
|
*******************************************
|
||||||
* Cryptomator Vault Health Report *
|
* Cryptomator Vault Health Report *
|
||||||
@@ -47,14 +43,14 @@ public class ReportWriter {
|
|||||||
|
|
||||||
private final Vault vault;
|
private final Vault vault;
|
||||||
private final VaultConfig vaultConfig;
|
private final VaultConfig vaultConfig;
|
||||||
private final RevealPathService revealPathService;
|
private final Application application;
|
||||||
private final Path exportDestination;
|
private final Path exportDestination;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public ReportWriter(@HealthCheckWindow Vault vault, AtomicReference<VaultConfig> vaultConfigRef, RevealPathService revealPathService, Environment env) {
|
public ReportWriter(@HealthCheckWindow Vault vault, AtomicReference<VaultConfig> vaultConfigRef, Application application, Environment env) {
|
||||||
this.vault = vault;
|
this.vault = vault;
|
||||||
this.vaultConfig = Objects.requireNonNull(vaultConfigRef.get());
|
this.vaultConfig = Objects.requireNonNull(vaultConfigRef.get());
|
||||||
this.revealPathService = revealPathService;
|
this.application = application;
|
||||||
this.exportDestination = env.getLogDir().orElse(Path.of(System.getProperty("user.home"))).resolve("healthReport_" + vault.getDisplayName() + "_" + TIME_STAMP.format(Instant.now()) + ".log");
|
this.exportDestination = env.getLogDir().orElse(Path.of(System.getProperty("user.home"))).resolve("healthReport_" + vault.getDisplayName() + "_" + TIME_STAMP.format(Instant.now()) + ".log");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,11 +92,7 @@ public class ReportWriter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void reveal() {
|
private void reveal() {
|
||||||
try {
|
application.getHostServices().showDocument(exportDestination.getParent().toUri().toString());
|
||||||
revealPathService.reveal(exportDestination.getParent());
|
|
||||||
} catch (RevealFailedException e) {
|
|
||||||
LOG.warn("Failed to reveal export destination location of report", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import org.cryptomator.common.vaults.Vault;
|
|||||||
import org.cryptomator.ui.common.FxController;
|
import org.cryptomator.ui.common.FxController;
|
||||||
import org.cryptomator.ui.common.FxmlFile;
|
import org.cryptomator.ui.common.FxmlFile;
|
||||||
import org.cryptomator.ui.common.FxmlScene;
|
import org.cryptomator.ui.common.FxmlScene;
|
||||||
import org.cryptomator.ui.dialogs.Dialogs;
|
|
||||||
import org.cryptomator.ui.keyloading.KeyLoading;
|
import org.cryptomator.ui.keyloading.KeyLoading;
|
||||||
import org.cryptomator.ui.keyloading.KeyLoadingScoped;
|
import org.cryptomator.ui.keyloading.KeyLoadingScoped;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
@@ -59,8 +58,6 @@ public class ReceiveKeyController implements FxController {
|
|||||||
private final Lazy<Scene> accountInitializationScene;
|
private final Lazy<Scene> accountInitializationScene;
|
||||||
private final Lazy<Scene> invalidLicenseScene;
|
private final Lazy<Scene> invalidLicenseScene;
|
||||||
private final HttpClient httpClient;
|
private final HttpClient httpClient;
|
||||||
private final Dialogs dialogs;
|
|
||||||
private final Vault vault;
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public ReceiveKeyController(@KeyLoading Vault vault, //
|
public ReceiveKeyController(@KeyLoading Vault vault, //
|
||||||
@@ -75,8 +72,7 @@ public class ReceiveKeyController implements FxController {
|
|||||||
@FxmlScene(FxmlFile.HUB_LEGACY_REGISTER_DEVICE) Lazy<Scene> legacyRegisterDeviceScene, //
|
@FxmlScene(FxmlFile.HUB_LEGACY_REGISTER_DEVICE) Lazy<Scene> legacyRegisterDeviceScene, //
|
||||||
@FxmlScene(FxmlFile.HUB_UNAUTHORIZED_DEVICE) Lazy<Scene> unauthorizedScene, //
|
@FxmlScene(FxmlFile.HUB_UNAUTHORIZED_DEVICE) Lazy<Scene> unauthorizedScene, //
|
||||||
@FxmlScene(FxmlFile.HUB_REQUIRE_ACCOUNT_INIT) Lazy<Scene> accountInitializationScene, //
|
@FxmlScene(FxmlFile.HUB_REQUIRE_ACCOUNT_INIT) Lazy<Scene> accountInitializationScene, //
|
||||||
@FxmlScene(FxmlFile.HUB_INVALID_LICENSE) Lazy<Scene> invalidLicenseScene, //
|
@FxmlScene(FxmlFile.HUB_INVALID_LICENSE) Lazy<Scene> invalidLicenseScene) {
|
||||||
Dialogs dialogs) {
|
|
||||||
this.window = window;
|
this.window = window;
|
||||||
this.hubConfig = hubConfig;
|
this.hubConfig = hubConfig;
|
||||||
this.vaultId = extractVaultId(vault.getVaultConfigCache().getUnchecked().getKeyId()); // TODO: access vault config's JTI directly (requires changes in cryptofs)
|
this.vaultId = extractVaultId(vault.getVaultConfigCache().getUnchecked().getKeyId()); // TODO: access vault config's JTI directly (requires changes in cryptofs)
|
||||||
@@ -91,8 +87,6 @@ public class ReceiveKeyController implements FxController {
|
|||||||
this.invalidLicenseScene = invalidLicenseScene;
|
this.invalidLicenseScene = invalidLicenseScene;
|
||||||
this.window.addEventHandler(WindowEvent.WINDOW_HIDING, this::windowClosed);
|
this.window.addEventHandler(WindowEvent.WINDOW_HIDING, this::windowClosed);
|
||||||
this.httpClient = HttpClient.newBuilder().version(HttpClient.Version.HTTP_1_1).executor(executor).build();
|
this.httpClient = HttpClient.newBuilder().version(HttpClient.Version.HTTP_1_1).executor(executor).build();
|
||||||
this.dialogs = dialogs;
|
|
||||||
this.vault = vault;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
@@ -232,8 +226,7 @@ public class ReceiveKeyController implements FxController {
|
|||||||
switch (response.statusCode()) {
|
switch (response.statusCode()) {
|
||||||
case 200 -> receivedBothEncryptedKeys(response.body(), encryptedUserKey);
|
case 200 -> receivedBothEncryptedKeys(response.body(), encryptedUserKey);
|
||||||
case 402 -> licenseExceeded();
|
case 402 -> licenseExceeded();
|
||||||
case 403 -> accessNotGranted();
|
case 403, 410 -> accessNotGranted(); // or vault has been archived, effectively disallowing access - TODO: add specific dialog?
|
||||||
case 410 -> accessGoneVaultArchived();
|
|
||||||
case 449 -> accountInitializationRequired();
|
case 449 -> accountInitializationRequired();
|
||||||
default -> throw new IllegalStateException("Unexpected response " + response.statusCode());
|
default -> throw new IllegalStateException("Unexpected response " + response.statusCode());
|
||||||
}
|
}
|
||||||
@@ -277,8 +270,7 @@ public class ReceiveKeyController implements FxController {
|
|||||||
switch (response.statusCode()) {
|
switch (response.statusCode()) {
|
||||||
case 200 -> receivedLegacyAccessTokenSuccess(response.body());
|
case 200 -> receivedLegacyAccessTokenSuccess(response.body());
|
||||||
case 402 -> licenseExceeded();
|
case 402 -> licenseExceeded();
|
||||||
case 403 -> accessNotGranted();
|
case 403, 410 -> accessNotGranted(); // or vault has been archived, effectively disallowing access
|
||||||
case 410 -> accessGoneVaultArchived();
|
|
||||||
case 404 -> needsLegacyDeviceRegistration();
|
case 404 -> needsLegacyDeviceRegistration();
|
||||||
default -> throw new IOException("Unexpected response " + response.statusCode());
|
default -> throw new IOException("Unexpected response " + response.statusCode());
|
||||||
}
|
}
|
||||||
@@ -311,11 +303,6 @@ public class ReceiveKeyController implements FxController {
|
|||||||
window.setScene(unauthorizedScene.get());
|
window.setScene(unauthorizedScene.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void accessGoneVaultArchived() {
|
|
||||||
window.close();
|
|
||||||
dialogs.prepareHubVaultArchived((Stage)window.getOwner(), vault).build().showAndWait();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void accountInitializationRequired() {
|
private void accountInitializationRequired() {
|
||||||
window.setScene(accountInitializationScene.get());
|
window.setScene(accountInitializationScene.get());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,17 +2,14 @@ package org.cryptomator.ui.mainwindow;
|
|||||||
|
|
||||||
import org.cryptomator.common.vaults.Vault;
|
import org.cryptomator.common.vaults.Vault;
|
||||||
import org.cryptomator.common.vaults.VaultState;
|
import org.cryptomator.common.vaults.VaultState;
|
||||||
import org.cryptomator.integrations.revealpath.RevealFailedException;
|
|
||||||
import org.cryptomator.integrations.revealpath.RevealPathService;
|
|
||||||
import org.cryptomator.ui.common.Animations;
|
import org.cryptomator.ui.common.Animations;
|
||||||
import org.cryptomator.ui.common.AutoAnimator;
|
import org.cryptomator.ui.common.AutoAnimator;
|
||||||
import org.cryptomator.ui.common.FxController;
|
import org.cryptomator.ui.common.FxController;
|
||||||
import org.cryptomator.ui.controls.FontAwesome5Icon;
|
import org.cryptomator.ui.controls.FontAwesome5Icon;
|
||||||
import org.cryptomator.ui.controls.FontAwesome5IconView;
|
import org.cryptomator.ui.controls.FontAwesome5IconView;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
import javafx.application.Application;
|
||||||
import javafx.beans.binding.BooleanBinding;
|
import javafx.beans.binding.BooleanBinding;
|
||||||
import javafx.beans.property.ObjectProperty;
|
import javafx.beans.property.ObjectProperty;
|
||||||
import javafx.beans.property.ReadOnlyObjectProperty;
|
import javafx.beans.property.ReadOnlyObjectProperty;
|
||||||
@@ -22,12 +19,10 @@ import javafx.fxml.FXML;
|
|||||||
@MainWindowScoped
|
@MainWindowScoped
|
||||||
public class VaultDetailController implements FxController {
|
public class VaultDetailController implements FxController {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(VaultDetailController.class);
|
|
||||||
|
|
||||||
private final ReadOnlyObjectProperty<Vault> vault;
|
private final ReadOnlyObjectProperty<Vault> vault;
|
||||||
|
private final Application application;
|
||||||
private final ObservableValue<FontAwesome5Icon> glyph;
|
private final ObservableValue<FontAwesome5Icon> glyph;
|
||||||
private final BooleanBinding anyVaultSelected;
|
private final BooleanBinding anyVaultSelected;
|
||||||
private final RevealPathService revealPathService;
|
|
||||||
|
|
||||||
private AutoAnimator spinAnimation;
|
private AutoAnimator spinAnimation;
|
||||||
|
|
||||||
@@ -36,11 +31,11 @@ public class VaultDetailController implements FxController {
|
|||||||
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
VaultDetailController(ObjectProperty<Vault> vault, RevealPathService revealPathService) {
|
VaultDetailController(ObjectProperty<Vault> vault, Application application) {
|
||||||
this.vault = vault;
|
this.vault = vault;
|
||||||
|
this.application = application;
|
||||||
this.glyph = vault.flatMap(Vault::stateProperty).map(this::getGlyphForVaultState);
|
this.glyph = vault.flatMap(Vault::stateProperty).map(this::getGlyphForVaultState);
|
||||||
this.anyVaultSelected = vault.isNotNull();
|
this.anyVaultSelected = vault.isNotNull();
|
||||||
this.revealPathService = revealPathService;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initialize() {
|
public void initialize() {
|
||||||
@@ -66,11 +61,7 @@ public class VaultDetailController implements FxController {
|
|||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
public void revealStorageLocation() {
|
public void revealStorageLocation() {
|
||||||
try {
|
application.getHostServices().showDocument(vault.get().getPath().toUri().toString());
|
||||||
revealPathService.reveal(vault.get().getPath());
|
|
||||||
} catch (RevealFailedException e) {
|
|
||||||
LOG.warn("Failed to reveal vault storage location", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Observable Properties */
|
/* Observable Properties */
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import org.slf4j.Logger;
|
|||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
import javafx.application.Platform;
|
||||||
import javafx.beans.property.BooleanProperty;
|
import javafx.beans.property.BooleanProperty;
|
||||||
import javafx.beans.property.ObjectProperty;
|
import javafx.beans.property.ObjectProperty;
|
||||||
import javafx.beans.property.ReadOnlyObjectProperty;
|
import javafx.beans.property.ReadOnlyObjectProperty;
|
||||||
@@ -30,6 +31,7 @@ import javafx.fxml.FXML;
|
|||||||
import javafx.scene.control.Button;
|
import javafx.scene.control.Button;
|
||||||
import javafx.scene.input.Clipboard;
|
import javafx.scene.input.Clipboard;
|
||||||
import javafx.scene.input.ClipboardContent;
|
import javafx.scene.input.ClipboardContent;
|
||||||
|
import javafx.scene.input.DataFormat;
|
||||||
import javafx.scene.input.DragEvent;
|
import javafx.scene.input.DragEvent;
|
||||||
import javafx.scene.input.TransferMode;
|
import javafx.scene.input.TransferMode;
|
||||||
import javafx.stage.FileChooser;
|
import javafx.stage.FileChooser;
|
||||||
@@ -38,8 +40,12 @@ import java.io.File;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.ResourceBundle;
|
import java.util.ResourceBundle;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
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;
|
||||||
|
|
||||||
@@ -54,7 +60,7 @@ public class VaultDetailUnlockedController implements FxController {
|
|||||||
private final VaultService vaultService;
|
private final VaultService vaultService;
|
||||||
private final WrongFileAlertComponent.Builder wrongFileAlert;
|
private final WrongFileAlertComponent.Builder wrongFileAlert;
|
||||||
private final Stage mainWindow;
|
private final Stage mainWindow;
|
||||||
private final RevealPathService revealPathService;
|
private final Optional<RevealPathService> revealPathService;
|
||||||
private final DecryptNameComponent.Factory decryptNameWindowFactory;
|
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;
|
||||||
@@ -78,7 +84,7 @@ public class VaultDetailUnlockedController implements FxController {
|
|||||||
VaultStatisticsComponent.Builder vaultStatsBuilder, //
|
VaultStatisticsComponent.Builder vaultStatsBuilder, //
|
||||||
WrongFileAlertComponent.Builder wrongFileAlert, //
|
WrongFileAlertComponent.Builder wrongFileAlert, //
|
||||||
@MainWindow Stage mainWindow, //
|
@MainWindow Stage mainWindow, //
|
||||||
RevealPathService revealPathService, //
|
Optional<RevealPathService> revealPathService, //
|
||||||
DecryptNameComponent.Factory decryptNameWindowFactory, //
|
DecryptNameComponent.Factory decryptNameWindowFactory, //
|
||||||
ResourceBundle resourceBundle) {
|
ResourceBundle resourceBundle) {
|
||||||
this.vault = vault;
|
this.vault = vault;
|
||||||
@@ -105,7 +111,7 @@ public class VaultDetailUnlockedController implements FxController {
|
|||||||
|
|
||||||
public void initialize() {
|
public void initialize() {
|
||||||
revealEncryptedDropZone.setOnDragOver(e -> handleDragOver(e, draggingOverLocateEncrypted));
|
revealEncryptedDropZone.setOnDragOver(e -> handleDragOver(e, draggingOverLocateEncrypted));
|
||||||
revealEncryptedDropZone.setOnDragDropped(e -> handleDragDropped(e, this::getCiphertextPath, this::revealPaths));
|
revealEncryptedDropZone.setOnDragDropped(e -> handleDragDropped(e, this::getCiphertextPath, this::revealOrCopyPaths));
|
||||||
revealEncryptedDropZone.setOnDragExited(_ -> draggingOverLocateEncrypted.setValue(false));
|
revealEncryptedDropZone.setOnDragExited(_ -> draggingOverLocateEncrypted.setValue(false));
|
||||||
|
|
||||||
decryptNameDropZone.setOnDragOver(e -> handleDragOver(e, draggingOverDecryptName));
|
decryptNameDropZone.setOnDragOver(e -> handleDragOver(e, draggingOverDecryptName));
|
||||||
@@ -150,7 +156,7 @@ public class VaultDetailUnlockedController implements FxController {
|
|||||||
if (cleartextFile != null) {
|
if (cleartextFile != null) {
|
||||||
var ciphertextPath = getCiphertextPath(cleartextFile.toPath());
|
var ciphertextPath = getCiphertextPath(cleartextFile.toPath());
|
||||||
if (ciphertextPath != null) {
|
if (ciphertextPath != null) {
|
||||||
revealPaths(List.of(ciphertextPath));
|
revealOrCopyPaths(List.of(ciphertextPath));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -182,18 +188,34 @@ public class VaultDetailUnlockedController implements FxController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void revealPaths(List<Path> paths) {
|
private void revealOrCopyPaths(List<Path> paths) {
|
||||||
|
revealPathService.ifPresentOrElse(svc -> revealPaths(svc, paths), () -> {
|
||||||
|
LOG.warn("No service provider to reveal files found.");
|
||||||
|
copyPathsToClipboard(paths);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void revealPaths(RevealPathService service, List<Path> paths) {
|
||||||
paths.forEach(path -> {
|
paths.forEach(path -> {
|
||||||
try {
|
try {
|
||||||
LOG.debug("Revealing {}", path);
|
LOG.debug("Revealing {}", path);
|
||||||
revealPathService.reveal(path);
|
service.reveal(path);
|
||||||
} catch (RevealFailedException e) {
|
} catch (RevealFailedException e) {
|
||||||
//TODO: show popup in ui
|
|
||||||
LOG.error("Revealing ciphertext file failed.", e);
|
LOG.error("Revealing ciphertext file failed.", e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void copyPathsToClipboard(List<Path> paths) {
|
||||||
|
StringBuilder clipboardString = new StringBuilder();
|
||||||
|
paths.forEach(p -> clipboardString.append(p.toString()).append("\n"));
|
||||||
|
Clipboard.getSystemClipboard().setContent(Map.of(DataFormat.PLAIN_TEXT, clipboardString.toString()));
|
||||||
|
ciphertextPathsCopied.setValue(true);
|
||||||
|
CompletableFuture.delayedExecutor(2, TimeUnit.SECONDS, Platform::runLater).execute(() -> {
|
||||||
|
ciphertextPathsCopied.set(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private VaultStatisticsComponent buildVaultStats(Vault vault) {
|
private VaultStatisticsComponent buildVaultStats(Vault vault) {
|
||||||
return vaultStatsBuilder.vault(vault).build();
|
return vaultStatsBuilder.vault(vault).build();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ import javafx.beans.value.ObservableValue;
|
|||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.geometry.Insets;
|
import javafx.geometry.Insets;
|
||||||
import javafx.scene.layout.HBox;
|
import javafx.scene.layout.HBox;
|
||||||
import java.util.ResourceBundle;
|
|
||||||
|
|
||||||
// unscoped because each cell needs its own controller
|
// unscoped because each cell needs its own controller
|
||||||
public class VaultListCellController implements FxController {
|
public class VaultListCellController implements FxController {
|
||||||
@@ -24,12 +23,9 @@ public class VaultListCellController implements FxController {
|
|||||||
private static final Insets COMPACT_INSETS = new Insets(6, 12, 6, 12);
|
private static final Insets COMPACT_INSETS = new Insets(6, 12, 6, 12);
|
||||||
private static final Insets DEFAULT_INSETS = new Insets(12);
|
private static final Insets DEFAULT_INSETS = new Insets(12);
|
||||||
|
|
||||||
private final ResourceBundle resourceBundle;
|
|
||||||
private final ObjectProperty<Vault> vault = new SimpleObjectProperty<>();
|
private final ObjectProperty<Vault> vault = new SimpleObjectProperty<>();
|
||||||
private final ObservableValue<VaultState.Value> vaultState;
|
|
||||||
private final ObservableValue<FontAwesome5Icon> glyph;
|
private final ObservableValue<FontAwesome5Icon> glyph;
|
||||||
private final ObservableValue<Boolean> compactMode;
|
private final ObservableValue<Boolean> compactMode;
|
||||||
private final ObservableValue<String> accessibleText;
|
|
||||||
|
|
||||||
private AutoAnimator spinAnimation;
|
private AutoAnimator spinAnimation;
|
||||||
|
|
||||||
@@ -39,21 +35,17 @@ public class VaultListCellController implements FxController {
|
|||||||
public HBox vaultListCell;
|
public HBox vaultListCell;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
VaultListCellController(Settings settings, ResourceBundle resourceBundle) {
|
VaultListCellController(Settings settings) {
|
||||||
this.resourceBundle = resourceBundle;
|
this.glyph = vault.flatMap(Vault::stateProperty).map(this::getGlyphForVaultState);
|
||||||
this.vaultState = vault.flatMap(Vault::stateProperty);
|
|
||||||
this.glyph = vaultState.map(this::getGlyphForVaultState);
|
|
||||||
this.accessibleText = vaultState.map(this::getAccessibleTextForVaultState);
|
|
||||||
this.compactMode = settings.compactMode;
|
this.compactMode = settings.compactMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initialize() {
|
public void initialize() {
|
||||||
this.spinAnimation = AutoAnimator.animate(Animations.createDiscrete360Rotation(vaultStateView)) //
|
this.spinAnimation = AutoAnimator.animate(Animations.createDiscrete360Rotation(vaultStateView)) //
|
||||||
.onCondition(vaultState.map(VaultState.Value.PROCESSING::equals).orElse(false)) //
|
.onCondition(vault.flatMap(Vault::stateProperty).map(VaultState.Value.PROCESSING::equals).orElse(false)) //
|
||||||
.afterStop(() -> vaultStateView.setRotate(0)) //
|
.afterStop(() -> vaultStateView.setRotate(0)) //
|
||||||
.build();
|
.build();
|
||||||
this.vaultListCell.paddingProperty().bind(compactMode.map(c -> c ? COMPACT_INSETS : DEFAULT_INSETS));
|
this.vaultListCell.paddingProperty().bind(compactMode.map(c -> c ? COMPACT_INSETS : DEFAULT_INSETS));
|
||||||
this.vaultListCell.accessibleTextProperty().bind(accessibleText);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO deduplicate w/ VaultDetailController
|
// TODO deduplicate w/ VaultDetailController
|
||||||
@@ -70,25 +62,6 @@ public class VaultListCellController implements FxController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getAccessibleTextForVaultState(VaultState.Value state) {
|
|
||||||
var v = vault.get();
|
|
||||||
if (state != null && v != null) {
|
|
||||||
var translationKey = switch (state) {
|
|
||||||
case LOCKED -> "vault.state.locked";
|
|
||||||
case PROCESSING -> "vault.state.processing";
|
|
||||||
case UNLOCKED -> "vault.state.unlocked";
|
|
||||||
case NEEDS_MIGRATION -> "vault.state.migrationNeeded";
|
|
||||||
case MISSING -> "vault.state.missing";
|
|
||||||
case VAULT_CONFIG_MISSING, ALL_MISSING, ERROR -> "vault.state.error";
|
|
||||||
};
|
|
||||||
|
|
||||||
var localizedState = resourceBundle.getString(translationKey);
|
|
||||||
return resourceBundle.getString("main.vaultlist.listEntry").formatted(v.getDisplayName(), localizedState);
|
|
||||||
} else {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Getter/Setter */
|
/* Getter/Setter */
|
||||||
|
|
||||||
public ObservableValue<FontAwesome5Icon> glyphProperty() {
|
public ObservableValue<FontAwesome5Icon> glyphProperty() {
|
||||||
|
|||||||
@@ -101,10 +101,15 @@ public class NotificationController implements FxController {
|
|||||||
var device = userAndDevice.length == 1 ? userAndDevice[0] : userAndDevice[1];
|
var device = userAndDevice.length == 1 ? userAndDevice[0] : userAndDevice[1];
|
||||||
var cleartextFileName = fiiue.cleartextPath().substring(fiiue.cleartextPath().lastIndexOf('/') + 1);
|
var cleartextFileName = fiiue.cleartextPath().substring(fiiue.cleartextPath().lastIndexOf('/') + 1);
|
||||||
eventTimestamp.set(localizedTimeFormatter.format(fiiue.lastUpdated()));
|
eventTimestamp.set(localizedTimeFormatter.format(fiiue.lastUpdated()));
|
||||||
message.set(resourceBundle.getString("notification.inUse.message"));
|
message.set("File is locked by another device");
|
||||||
fileName.set(cleartextFileName);
|
fileName.set(cleartextFileName);
|
||||||
description.set(resourceBundle.getString("notification.inUse.description").formatted(user, device));
|
description.set("The file is opened by %s on device %s. Ask the user to close the file and sync again. Otherwise, you can ignore the lock and open it anyway.".formatted(user, device));
|
||||||
|
actionText.set("Ignore Lock");
|
||||||
|
/* TODO: Once feature is out of beta, activate translations
|
||||||
|
message.set(resourceBundle.getString("notification.inUse.message"));
|
||||||
|
description.set(resourceBundle.getString("notification.inUse.description").formatted(fiiue.cleartextPath(), user, device));
|
||||||
actionText.set(resourceBundle.getString("notification.inUse.action"));
|
actionText.set(resourceBundle.getString("notification.inUse.action"));
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
default -> {
|
default -> {
|
||||||
message.set("NO CONTENT");
|
message.set("NO CONTENT");
|
||||||
|
|||||||
@@ -10,14 +10,13 @@ import org.cryptomator.integrations.common.NamedServiceProvider;
|
|||||||
import org.cryptomator.integrations.keychain.KeychainAccessException;
|
import org.cryptomator.integrations.keychain.KeychainAccessException;
|
||||||
import org.cryptomator.integrations.keychain.KeychainAccessProvider;
|
import org.cryptomator.integrations.keychain.KeychainAccessProvider;
|
||||||
import org.cryptomator.integrations.quickaccess.QuickAccessService;
|
import org.cryptomator.integrations.quickaccess.QuickAccessService;
|
||||||
import org.cryptomator.integrations.revealpath.RevealFailedException;
|
|
||||||
import org.cryptomator.integrations.revealpath.RevealPathService;
|
|
||||||
import org.cryptomator.ui.common.FxController;
|
import org.cryptomator.ui.common.FxController;
|
||||||
import org.cryptomator.ui.fxapp.FxApplicationWindows;
|
import org.cryptomator.ui.fxapp.FxApplicationWindows;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
import javafx.application.Application;
|
||||||
import javafx.beans.Observable;
|
import javafx.beans.Observable;
|
||||||
import javafx.beans.binding.Bindings;
|
import javafx.beans.binding.Bindings;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
@@ -42,7 +41,7 @@ public class GeneralPreferencesController implements FxController {
|
|||||||
private final Settings settings;
|
private final Settings settings;
|
||||||
private final Optional<AutoStartProvider> autoStartProvider;
|
private final Optional<AutoStartProvider> autoStartProvider;
|
||||||
private final List<QuickAccessService> quickAccessServices;
|
private final List<QuickAccessService> quickAccessServices;
|
||||||
private final RevealPathService revealPathService;
|
private final Application application;
|
||||||
private final Environment environment;
|
private final Environment environment;
|
||||||
private final List<KeychainAccessProvider> keychainAccessProviders;
|
private final List<KeychainAccessProvider> keychainAccessProviders;
|
||||||
private final KeychainManager keychain;
|
private final KeychainManager keychain;
|
||||||
@@ -61,15 +60,9 @@ public class GeneralPreferencesController implements FxController {
|
|||||||
private CompletionStage<Void> keychainMigrations = CompletableFuture.completedFuture(null);
|
private CompletionStage<Void> keychainMigrations = CompletableFuture.completedFuture(null);
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
GeneralPreferencesController(@PreferencesWindow Stage window, //
|
GeneralPreferencesController(@PreferencesWindow Stage window, Settings settings, Optional<AutoStartProvider> autoStartProvider, //
|
||||||
Settings settings, //
|
List<KeychainAccessProvider> keychainAccessProviders, KeychainManager keychain, Application application, //
|
||||||
Optional<AutoStartProvider> autoStartProvider, //
|
Environment environment, FxApplicationWindows appWindows, ExecutorService backgroundExecutor) {
|
||||||
List<KeychainAccessProvider> keychainAccessProviders, //
|
|
||||||
KeychainManager keychain, //
|
|
||||||
RevealPathService revealPathService, //
|
|
||||||
Environment environment, //
|
|
||||||
FxApplicationWindows appWindows, //
|
|
||||||
ExecutorService backgroundExecutor) {
|
|
||||||
this.window = window;
|
this.window = window;
|
||||||
this.settings = settings;
|
this.settings = settings;
|
||||||
this.autoStartProvider = autoStartProvider;
|
this.autoStartProvider = autoStartProvider;
|
||||||
@@ -77,7 +70,7 @@ public class GeneralPreferencesController implements FxController {
|
|||||||
this.keychain = keychain;
|
this.keychain = keychain;
|
||||||
this.backgroundExecutor = backgroundExecutor;
|
this.backgroundExecutor = backgroundExecutor;
|
||||||
this.quickAccessServices = QuickAccessService.get().toList();
|
this.quickAccessServices = QuickAccessService.get().toList();
|
||||||
this.revealPathService = revealPathService;
|
this.application = application;
|
||||||
this.environment = environment;
|
this.environment = environment;
|
||||||
this.appWindows = appWindows;
|
this.appWindows = appWindows;
|
||||||
}
|
}
|
||||||
@@ -108,9 +101,8 @@ public class GeneralPreferencesController implements FxController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void migrateKeychainEntries(Observable observable, KeychainAccessProvider oldProvider, KeychainAccessProvider newProvider) {
|
private void migrateKeychainEntries(Observable observable, KeychainAccessProvider oldProvider, KeychainAccessProvider newProvider) {
|
||||||
//currently, we migrate on macOS (touchID vs regular keychain)
|
//currently, we only migrate on macOS (touchID vs regular keychain)
|
||||||
//and on Linux (GNOME Keyring / KDE Wallet / Secret Service)
|
if (SystemUtils.IS_OS_MAC) {
|
||||||
if (SystemUtils.IS_OS_MAC || SystemUtils.IS_OS_LINUX) {
|
|
||||||
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()) {
|
||||||
@@ -155,11 +147,7 @@ public class GeneralPreferencesController implements FxController {
|
|||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
public void showLogfileDirectory() {
|
public void showLogfileDirectory() {
|
||||||
try {
|
environment.getLogDir().ifPresent(logDirPath -> application.getHostServices().showDocument(logDirPath.toUri().toString()));
|
||||||
revealPathService.reveal(environment.getLogDir().orElseThrow());
|
|
||||||
} catch (RevealFailedException e) {
|
|
||||||
LOG.warn("Failed to reveal log files directory.", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Helper classes */
|
/* Helper classes */
|
||||||
@@ -207,5 +195,4 @@ public class GeneralPreferencesController implements FxController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ public class InterfacePreferencesController implements FxController {
|
|||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
public void initialize() {
|
public void initialize() {
|
||||||
themeChoiceBox.getItems().addAll(UiTheme.values());
|
themeChoiceBox.getItems().addAll(UiTheme.applicableValues());
|
||||||
if (!themeChoiceBox.getItems().contains(settings.theme.get())) {
|
if (!themeChoiceBox.getItems().contains(settings.theme.get())) {
|
||||||
settings.theme.set(UiTheme.LIGHT);
|
settings.theme.set(UiTheme.LIGHT);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,19 +3,18 @@ package org.cryptomator.ui.preferences;
|
|||||||
import org.cryptomator.common.Environment;
|
import org.cryptomator.common.Environment;
|
||||||
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.integrations.revealpath.RevealFailedException;
|
|
||||||
import org.cryptomator.integrations.revealpath.RevealPathService;
|
|
||||||
import org.cryptomator.integrations.update.UpdateStep;
|
import org.cryptomator.integrations.update.UpdateStep;
|
||||||
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.updater.FallbackUpdateInfo;
|
|
||||||
import org.cryptomator.updater.UpdateChecker;
|
import org.cryptomator.updater.UpdateChecker;
|
||||||
|
import org.cryptomator.updater.FallbackUpdateInfo;
|
||||||
import org.cryptomator.updater.UpdateService;
|
import org.cryptomator.updater.UpdateService;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javafx.animation.PauseTransition;
|
import javafx.animation.PauseTransition;
|
||||||
|
import javafx.application.Application;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.beans.binding.Bindings;
|
import javafx.beans.binding.Bindings;
|
||||||
import javafx.beans.binding.BooleanBinding;
|
import javafx.beans.binding.BooleanBinding;
|
||||||
@@ -50,7 +49,7 @@ public class UpdatesPreferencesController implements FxController {
|
|||||||
private static final Logger LOG = LoggerFactory.getLogger(UpdatesPreferencesController.class);
|
private static final Logger LOG = LoggerFactory.getLogger(UpdatesPreferencesController.class);
|
||||||
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM).withLocale(Locale.getDefault());
|
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM).withLocale(Locale.getDefault());
|
||||||
|
|
||||||
private final RevealPathService revealPathService;
|
private final Application application;
|
||||||
private final Environment environment;
|
private final Environment environment;
|
||||||
private final ResourceBundle resourceBundle;
|
private final ResourceBundle resourceBundle;
|
||||||
private final Settings settings;
|
private final Settings settings;
|
||||||
@@ -73,8 +72,8 @@ public class UpdatesPreferencesController implements FxController {
|
|||||||
public CheckBox checkForUpdatesCheckbox;
|
public CheckBox checkForUpdatesCheckbox;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
UpdatesPreferencesController(RevealPathService revealPathService, Environment environment, ResourceBundle resourceBundle, Settings settings, UpdateChecker updateChecker, ObservableList<Vault> vaults, VaultService vaultService) {
|
UpdatesPreferencesController(Application application, Environment environment, ResourceBundle resourceBundle, Settings settings, UpdateChecker updateChecker, ObservableList<Vault> vaults, VaultService vaultService) {
|
||||||
this.revealPathService = revealPathService;
|
this.application = application;
|
||||||
this.environment = environment;
|
this.environment = environment;
|
||||||
this.resourceBundle = resourceBundle;
|
this.resourceBundle = resourceBundle;
|
||||||
this.settings = settings;
|
this.settings = settings;
|
||||||
@@ -107,14 +106,9 @@ public class UpdatesPreferencesController implements FxController {
|
|||||||
updateService.setOnFailed(this::updateFailed);
|
updateService.setOnFailed(this::updateFailed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
public void showLogfileDirectory() {
|
public void showLogfileDirectory() {
|
||||||
try {
|
environment.getLogDir().ifPresent(logDirPath -> application.getHostServices().showDocument(logDirPath.toUri().toString()));
|
||||||
revealPathService.reveal(environment.getLogDir().orElseThrow());
|
|
||||||
} catch (RevealFailedException e) {
|
|
||||||
LOG.warn("Failed to reveal log files directory.", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ public class RecoveryKeyCreationController implements FxController {
|
|||||||
descriptionLabel.formatProperty().set(resourceBundle.getString("recoveryKey.recover.description"));
|
descriptionLabel.formatProperty().set(resourceBundle.getString("recoveryKey.recover.description"));
|
||||||
cancelButton.setOnAction((_) -> back());
|
cancelButton.setOnAction((_) -> back());
|
||||||
cancelButton.setText(resourceBundle.getString("generic.button.back"));
|
cancelButton.setText(resourceBundle.getString("generic.button.back"));
|
||||||
nextButton.setOnAction((_) -> restoreWithPasswordAsync());
|
nextButton.setOnAction((_) -> restoreWithPassword());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,47 +137,11 @@ public class RecoveryKeyCreationController implements FxController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
public void restoreWithPasswordAsync() {
|
public void restoreWithPassword() {
|
||||||
Task<Void> task = RecoveryKeyTasks.createTask(this::restoreWithPassword);
|
|
||||||
|
|
||||||
task.setOnScheduled(_ -> {
|
|
||||||
LOG.debug("Restoring vault configuration with password for {}.", vault.getDisplayablePath());
|
|
||||||
});
|
|
||||||
|
|
||||||
task.setOnSucceeded(_ -> {
|
|
||||||
LOG.debug("Restored vault configuration for {}.", vault.getDisplayablePath());
|
|
||||||
try {
|
|
||||||
if (!vaultListManager.isAlreadyAdded(vault.getPath())) {
|
|
||||||
vaultListManager.add(vault.getPath());
|
|
||||||
}
|
|
||||||
window.close();
|
|
||||||
dialogs.prepareRecoverPasswordSuccess((Stage) window.getOwner()) //
|
|
||||||
.setTitleKey("recover.recoverVaultConfig.title") //
|
|
||||||
.setMessageKey("recoveryKey.recover.resetVaultConfigSuccess.message") //
|
|
||||||
.setDescriptionKey("recoveryKey.recover.resetMasterkeyFileSuccess.description")
|
|
||||||
.build().showAndWait();
|
|
||||||
} catch (IOException e) {
|
|
||||||
LOG.error("Failed to add vault to list.", e);
|
|
||||||
appWindows.showErrorWindow(e, window, null);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
task.setOnFailed(_ -> {
|
|
||||||
if (task.getException() instanceof InvalidPassphraseException e) {
|
|
||||||
LOG.info("Password invalid", e);
|
|
||||||
Animations.createShakeWindowAnimation(window).play();
|
|
||||||
} else {
|
|
||||||
LOG.error("Recovery process failed.", task.getException());
|
|
||||||
appWindows.showErrorWindow(task.getException(), window, null);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
executor.submit(task);
|
|
||||||
}
|
|
||||||
|
|
||||||
void restoreWithPassword() throws IOException, CryptoException {
|
|
||||||
try (RecoveryDirectory recoveryDirectory = RecoveryDirectory.create(vault.getPath())) {
|
try (RecoveryDirectory recoveryDirectory = RecoveryDirectory.create(vault.getPath())) {
|
||||||
Path recoveryPath = recoveryDirectory.getRecoveryPath();
|
Path recoveryPath = recoveryDirectory.getRecoveryPath();
|
||||||
|
|
||||||
Path masterkeyFilePath = vault.getPath().resolve(MASTERKEY_FILENAME);
|
Path masterkeyFilePath = vault.getPath().resolve(MASTERKEY_FILENAME);
|
||||||
|
|
||||||
try (Masterkey masterkey = MasterkeyService.load(masterkeyFileAccess, masterkeyFilePath, passwordField.getCharacters())) {
|
try (Masterkey masterkey = MasterkeyService.load(masterkeyFileAccess, masterkeyFilePath, passwordField.getCharacters())) {
|
||||||
@@ -188,6 +152,23 @@ public class RecoveryKeyCreationController implements FxController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
recoveryDirectory.moveRecoveredFile(VAULTCONFIG_FILENAME);
|
recoveryDirectory.moveRecoveredFile(VAULTCONFIG_FILENAME);
|
||||||
|
|
||||||
|
if (!vaultListManager.isAlreadyAdded(vault.getPath())) {
|
||||||
|
vaultListManager.add(vault.getPath());
|
||||||
|
}
|
||||||
|
window.close();
|
||||||
|
dialogs.prepareRecoverPasswordSuccess((Stage)window.getOwner()) //
|
||||||
|
.setTitleKey("recover.recoverVaultConfig.title") //
|
||||||
|
.setMessageKey("recoveryKey.recover.resetVaultConfigSuccess.message") //
|
||||||
|
.setDescriptionKey("recoveryKey.recover.resetMasterkeyFileSuccess.description")
|
||||||
|
.build().showAndWait();
|
||||||
|
|
||||||
|
} catch (InvalidPassphraseException e) {
|
||||||
|
LOG.info("Password invalid", e);
|
||||||
|
Animations.createShakeWindowAnimation(window).play();
|
||||||
|
} catch (IOException | CryptoException | IllegalStateException e) {
|
||||||
|
LOG.error("Recovery process failed", e);
|
||||||
|
appWindows.showErrorWindow(e, window, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+15
-34
@@ -117,46 +117,14 @@ public class RecoveryKeyResetPasswordController implements FxController {
|
|||||||
@FXML
|
@FXML
|
||||||
public void next() {
|
public void next() {
|
||||||
switch (recoverType.get()) {
|
switch (recoverType.get()) {
|
||||||
case RESTORE_ALL -> restorePasswordAsync();
|
case RESTORE_ALL -> restorePassword();
|
||||||
case RESTORE_MASTERKEY, RESET_PASSWORD -> resetPassword();
|
case RESTORE_MASTERKEY, RESET_PASSWORD -> resetPassword();
|
||||||
default -> resetPassword(); // Fallback
|
default -> resetPassword(); // Fallback
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
public void restorePasswordAsync() {
|
public void restorePassword() {
|
||||||
Task<Void> task = RecoveryKeyTasks.createTask(this::restorePassword);
|
|
||||||
|
|
||||||
task.setOnScheduled(_ -> {
|
|
||||||
LOG.debug("Restoring vault configuration for {}.", vault.getDisplayablePath());
|
|
||||||
});
|
|
||||||
|
|
||||||
task.setOnSucceeded(_ -> {
|
|
||||||
LOG.debug("Restored vault configuration for {}.", vault.getDisplayablePath());
|
|
||||||
try {
|
|
||||||
if (!vaultListManager.isAlreadyAdded(vault.getPath())) {
|
|
||||||
vaultListManager.add(vault.getPath());
|
|
||||||
}
|
|
||||||
window.close();
|
|
||||||
dialogs.prepareRecoverPasswordSuccess((Stage) window.getOwner()) //
|
|
||||||
.setTitleKey("recover.recoverVaultConfig.title") //
|
|
||||||
.setMessageKey("recoveryKey.recover.resetVaultConfigSuccess.message") //
|
|
||||||
.build().showAndWait();
|
|
||||||
} catch (IOException e) {
|
|
||||||
LOG.error("Failed to add vault to list.", e);
|
|
||||||
appWindows.showErrorWindow(e, window, null);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
task.setOnFailed(_ -> {
|
|
||||||
LOG.error("Recovery process failed.", task.getException());
|
|
||||||
appWindows.showErrorWindow(task.getException(), window, null);
|
|
||||||
});
|
|
||||||
|
|
||||||
executor.submit(task);
|
|
||||||
}
|
|
||||||
|
|
||||||
void restorePassword() throws IOException, CryptoException {
|
|
||||||
try (RecoveryDirectory recoveryDirectory = RecoveryDirectory.create(vault.getPath())) {
|
try (RecoveryDirectory recoveryDirectory = RecoveryDirectory.create(vault.getPath())) {
|
||||||
Path recoveryPath = recoveryDirectory.getRecoveryPath();
|
Path recoveryPath = recoveryDirectory.getRecoveryPath();
|
||||||
MasterkeyService.recoverFromRecoveryKey(recoveryKey.get(), recoveryKeyFactory, recoveryPath, newPasswordController.passwordField.getCharacters());
|
MasterkeyService.recoverFromRecoveryKey(recoveryKey.get(), recoveryKeyFactory, recoveryPath, newPasswordController.passwordField.getCharacters());
|
||||||
@@ -167,6 +135,19 @@ public class RecoveryKeyResetPasswordController implements FxController {
|
|||||||
|
|
||||||
recoveryDirectory.moveRecoveredFile(MASTERKEY_FILENAME);
|
recoveryDirectory.moveRecoveredFile(MASTERKEY_FILENAME);
|
||||||
recoveryDirectory.moveRecoveredFile(VAULTCONFIG_FILENAME);
|
recoveryDirectory.moveRecoveredFile(VAULTCONFIG_FILENAME);
|
||||||
|
|
||||||
|
if (!vaultListManager.isAlreadyAdded(vault.getPath())) {
|
||||||
|
vaultListManager.add(vault.getPath());
|
||||||
|
}
|
||||||
|
window.close();
|
||||||
|
dialogs.prepareRecoverPasswordSuccess((Stage)window.getOwner()) //
|
||||||
|
.setTitleKey("recover.recoverVaultConfig.title") //
|
||||||
|
.setMessageKey("recoveryKey.recover.resetVaultConfigSuccess.message") //
|
||||||
|
.build().showAndWait();
|
||||||
|
|
||||||
|
} catch (IOException | CryptoException e) {
|
||||||
|
LOG.error("Recovery process failed", e);
|
||||||
|
appWindows.showErrorWindow(e, window, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,25 +0,0 @@
|
|||||||
package org.cryptomator.ui.recoverykey;
|
|
||||||
|
|
||||||
import javafx.concurrent.Task;
|
|
||||||
|
|
||||||
final class RecoveryKeyTasks {
|
|
||||||
|
|
||||||
private RecoveryKeyTasks() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@FunctionalInterface
|
|
||||||
interface TaskAction {
|
|
||||||
void run() throws Exception;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Task<Void> createTask(TaskAction action) {
|
|
||||||
return new Task<Void>() {
|
|
||||||
@Override
|
|
||||||
protected Void call() throws Exception {
|
|
||||||
action.run();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -9,15 +9,11 @@ import org.cryptomator.ui.forgetpassword.ForgetPasswordComponent;
|
|||||||
import org.cryptomator.ui.recoverykey.RecoveryKeyComponent;
|
import org.cryptomator.ui.recoverykey.RecoveryKeyComponent;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javafx.beans.property.BooleanProperty;
|
|
||||||
import javafx.beans.property.SimpleBooleanProperty;
|
import javafx.beans.property.SimpleBooleanProperty;
|
||||||
import javafx.beans.property.SimpleObjectProperty;
|
import javafx.beans.property.SimpleObjectProperty;
|
||||||
import javafx.beans.value.ObservableValue;
|
import javafx.beans.value.ObservableValue;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.stage.Stage;
|
import javafx.stage.Stage;
|
||||||
import java.nio.file.Files;
|
|
||||||
|
|
||||||
import static org.cryptomator.common.Constants.MASTERKEY_FILENAME;
|
|
||||||
|
|
||||||
@VaultOptionsScoped
|
@VaultOptionsScoped
|
||||||
public class MasterkeyOptionsController implements FxController {
|
public class MasterkeyOptionsController implements FxController {
|
||||||
@@ -29,7 +25,6 @@ public class MasterkeyOptionsController implements FxController {
|
|||||||
private final ForgetPasswordComponent.Builder forgetPasswordWindow;
|
private final ForgetPasswordComponent.Builder forgetPasswordWindow;
|
||||||
private final KeychainManager keychain;
|
private final KeychainManager keychain;
|
||||||
private final ObservableValue<Boolean> passwordSaved;
|
private final ObservableValue<Boolean> passwordSaved;
|
||||||
private final BooleanProperty masterkeyFileAvailable;
|
|
||||||
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@@ -45,7 +40,6 @@ public class MasterkeyOptionsController implements FxController {
|
|||||||
} else {
|
} else {
|
||||||
this.passwordSaved = new SimpleBooleanProperty(false);
|
this.passwordSaved = new SimpleBooleanProperty(false);
|
||||||
}
|
}
|
||||||
this.masterkeyFileAvailable = new SimpleBooleanProperty(Files.exists(vault.getPath().resolve(MASTERKEY_FILENAME)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
@@ -76,12 +70,4 @@ public class MasterkeyOptionsController implements FxController {
|
|||||||
public boolean isPasswordSaved() {
|
public boolean isPasswordSaved() {
|
||||||
return passwordSaved.getValue();
|
return passwordSaved.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
public BooleanProperty masterkeyFileAvailableProperty() {
|
|
||||||
return masterkeyFileAvailable;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isMasterkeyFileAvailable() {
|
|
||||||
return masterkeyFileAvailable.get();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,7 +50,6 @@
|
|||||||
GREEN_5: PRIMARY;
|
GREEN_5: PRIMARY;
|
||||||
RED_5: #E74C3C;
|
RED_5: #E74C3C;
|
||||||
ORANGE_5: #E67E22;
|
ORANGE_5: #E67E22;
|
||||||
YELLOW_4: #C19F0E;
|
|
||||||
YELLOW_5: #F1C40F;
|
YELLOW_5: #F1C40F;
|
||||||
|
|
||||||
MAIN_BG: GRAY_1;
|
MAIN_BG: GRAY_1;
|
||||||
@@ -388,62 +387,37 @@
|
|||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* *
|
* *
|
||||||
* InfoBar *
|
* NotificationBar *
|
||||||
* *
|
* *
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
.info-bar {
|
|
||||||
-fx-alignment: center;
|
.notification-label {
|
||||||
|
-fx-text-fill: white;
|
||||||
|
-fx-font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notification-debug {
|
||||||
-fx-min-height:24px;
|
-fx-min-height:24px;
|
||||||
-fx-max-height:24px;
|
-fx-max-height:24px;
|
||||||
-fx-background-color: -bar-bg;
|
-fx-background-color: RED_5;
|
||||||
}
|
}
|
||||||
|
|
||||||
.info-bar--green {
|
.notification-update {
|
||||||
-bar-bg: GREEN_5;
|
-fx-min-height:24px;
|
||||||
-button-bg: GREEN_5;
|
-fx-max-height:24px;
|
||||||
-button-bg-pressed: GREEN_3;
|
-fx-background-color: YELLOW_5;
|
||||||
}
|
}
|
||||||
|
|
||||||
.info-bar--yellow {
|
.notification-support {
|
||||||
-bar-bg: YELLOW_5;
|
-fx-min-height:24px;
|
||||||
-button-bg: YELLOW_5;
|
-fx-max-height:24px;
|
||||||
-button-bg-pressed: YELLOW_4;
|
-fx-background-color: PRIMARY;
|
||||||
}
|
}
|
||||||
|
|
||||||
.info-bar--red {
|
.notification-debug:hover .notification-label,
|
||||||
-bar-bg: RED_5;
|
.notification-update:hover .notification-label,
|
||||||
-button-bg: RED_5;
|
.notification-support:hover .notification-label {
|
||||||
-button-bg-pressed: RED_5;
|
-fx-underline:true;
|
||||||
}
|
|
||||||
|
|
||||||
.info-bar .label {
|
|
||||||
-fx-text-fill: GRAY_9;
|
|
||||||
-fx-font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.info-bar--yellow .label {
|
|
||||||
-fx-text-fill: GRAY_9;
|
|
||||||
-fx-font-weight: bold;
|
|
||||||
-fx-effect: dropshadow( gaussian , rgba(0,0,0,0.45) , 2 , 0 , 0 , 1 );
|
|
||||||
}
|
|
||||||
|
|
||||||
.info-bar .glyph {
|
|
||||||
-fx-fill: GRAY_9;
|
|
||||||
}
|
|
||||||
|
|
||||||
.info-bar:hover .label {
|
|
||||||
-fx-underline:true;
|
|
||||||
}
|
|
||||||
|
|
||||||
.info-bar .button {
|
|
||||||
-fx-background-color: transparent;
|
|
||||||
-fx-border-color: transparent;
|
|
||||||
-fx-padding: 2 2 2 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.info-bar .button:armed {
|
|
||||||
-fx-background-color: -button-bg-pressed;
|
|
||||||
-fx-background-radius: 8;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
|||||||
@@ -50,7 +50,6 @@
|
|||||||
GREEN_5: PRIMARY;
|
GREEN_5: PRIMARY;
|
||||||
RED_5: #E74C3C;
|
RED_5: #E74C3C;
|
||||||
ORANGE_5: #E67E22;
|
ORANGE_5: #E67E22;
|
||||||
YELLOW_4: #C19F0E;
|
|
||||||
YELLOW_5: #F1C40F;
|
YELLOW_5: #F1C40F;
|
||||||
|
|
||||||
MAIN_BG: GRAY_9;
|
MAIN_BG: GRAY_9;
|
||||||
@@ -388,64 +387,39 @@
|
|||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* *
|
* *
|
||||||
* InfoBar *
|
* NotificationBar *
|
||||||
* *
|
* *
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
.info-bar {
|
|
||||||
-fx-alignment: center;
|
.notification-label {
|
||||||
|
-fx-text-fill: white;
|
||||||
|
-fx-font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notification-debug {
|
||||||
-fx-min-height:24px;
|
-fx-min-height:24px;
|
||||||
-fx-max-height:24px;
|
-fx-max-height:24px;
|
||||||
-fx-background-color: -bar-bg;
|
-fx-background-color: RED_5;
|
||||||
}
|
}
|
||||||
|
|
||||||
.info-bar--green {
|
.notification-update {
|
||||||
-bar-bg: GREEN_5;
|
-fx-min-height:24px;
|
||||||
-button-bg: GREEN_5;
|
-fx-max-height:24px;
|
||||||
-button-bg-pressed: GREEN_3;
|
-fx-background-color: YELLOW_5;
|
||||||
}
|
}
|
||||||
|
|
||||||
.info-bar--yellow {
|
.notification-support {
|
||||||
-bar-bg: YELLOW_5;
|
-fx-min-height:24px;
|
||||||
-button-bg: YELLOW_5;
|
-fx-max-height:24px;
|
||||||
-button-bg-pressed: YELLOW_4;
|
-fx-background-color: PRIMARY;
|
||||||
}
|
}
|
||||||
|
|
||||||
.info-bar--red {
|
.notification-debug:hover .notification-label,
|
||||||
-bar-bg: RED_5;
|
.notification-update:hover .notification-label,
|
||||||
-button-bg: RED_5;
|
.notification-support:hover .notification-label {
|
||||||
-button-bg-pressed: RED_5;
|
|
||||||
}
|
|
||||||
|
|
||||||
.info-bar .label {
|
|
||||||
-fx-text-fill: GRAY_9;
|
|
||||||
-fx-font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.info-bar--yellow .label {
|
|
||||||
-fx-text-fill: GRAY_9;
|
|
||||||
-fx-font-weight: bold;
|
|
||||||
-fx-effect: dropshadow( gaussian , rgba(0,0,0,0.45) , 2 , 0 , 0 , 1 );
|
|
||||||
}
|
|
||||||
|
|
||||||
.info-bar .glyph {
|
|
||||||
-fx-fill: GRAY_9;
|
|
||||||
}
|
|
||||||
|
|
||||||
.info-bar:hover .label {
|
|
||||||
-fx-underline:true;
|
-fx-underline:true;
|
||||||
}
|
}
|
||||||
|
|
||||||
.info-bar .button {
|
|
||||||
-fx-background-color: transparent;
|
|
||||||
-fx-border-color: transparent;
|
|
||||||
-fx-padding: 2 2 2 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.info-bar .button:armed {
|
|
||||||
-fx-background-color: -button-bg-pressed;
|
|
||||||
-fx-background-radius: 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* *
|
* *
|
||||||
* ScrollBar *
|
* ScrollBar *
|
||||||
|
|||||||
@@ -13,8 +13,7 @@
|
|||||||
prefWidth="450"
|
prefWidth="450"
|
||||||
prefHeight="450"
|
prefHeight="450"
|
||||||
spacing="24"
|
spacing="24"
|
||||||
alignment="CENTER"
|
alignment="CENTER">
|
||||||
accessibleRole="DIALOG">
|
|
||||||
<padding>
|
<padding>
|
||||||
<Insets topRightBottomLeft="24"/>
|
<Insets topRightBottomLeft="24"/>
|
||||||
</padding>
|
</padding>
|
||||||
|
|||||||
@@ -19,8 +19,7 @@
|
|||||||
prefWidth="450"
|
prefWidth="450"
|
||||||
prefHeight="450"
|
prefHeight="450"
|
||||||
spacing="12"
|
spacing="12"
|
||||||
alignment="CENTER_LEFT"
|
alignment="CENTER_LEFT">
|
||||||
accessibleRole="DIALOG">
|
|
||||||
<padding>
|
<padding>
|
||||||
<Insets topRightBottomLeft="24"/>
|
<Insets topRightBottomLeft="24"/>
|
||||||
</padding>
|
</padding>
|
||||||
|
|||||||
@@ -19,8 +19,7 @@
|
|||||||
prefWidth="450"
|
prefWidth="450"
|
||||||
prefHeight="450"
|
prefHeight="450"
|
||||||
spacing="12"
|
spacing="12"
|
||||||
alignment="CENTER_LEFT"
|
alignment="CENTER_LEFT">
|
||||||
accessibleRole="DIALOG">
|
|
||||||
<fx:define>
|
<fx:define>
|
||||||
<ToggleGroup fx:id="locationPresetsToggler"/>
|
<ToggleGroup fx:id="locationPresetsToggler"/>
|
||||||
<FontAwesome5IconView fx:id="badLocation" styleClass="glyph-icon-red" glyph="TIMES"/>
|
<FontAwesome5IconView fx:id="badLocation" styleClass="glyph-icon-red" glyph="TIMES"/>
|
||||||
|
|||||||
@@ -17,8 +17,7 @@
|
|||||||
prefWidth="450"
|
prefWidth="450"
|
||||||
prefHeight="450"
|
prefHeight="450"
|
||||||
spacing="12"
|
spacing="12"
|
||||||
alignment="CENTER_LEFT"
|
alignment="CENTER_LEFT">
|
||||||
accessibleRole="DIALOG">
|
|
||||||
<padding>
|
<padding>
|
||||||
<Insets topRightBottomLeft="24"/>
|
<Insets topRightBottomLeft="24"/>
|
||||||
</padding>
|
</padding>
|
||||||
|
|||||||
@@ -15,8 +15,7 @@
|
|||||||
prefWidth="450"
|
prefWidth="450"
|
||||||
prefHeight="450"
|
prefHeight="450"
|
||||||
spacing="12"
|
spacing="12"
|
||||||
alignment="CENTER_LEFT"
|
alignment="CENTER_LEFT">
|
||||||
accessibleRole="DIALOG">
|
|
||||||
<fx:define>
|
<fx:define>
|
||||||
<ToggleGroup fx:id="recoveryKeyChoice"/>
|
<ToggleGroup fx:id="recoveryKeyChoice"/>
|
||||||
</fx:define>
|
</fx:define>
|
||||||
|
|||||||
@@ -11,8 +11,7 @@
|
|||||||
prefWidth="450"
|
prefWidth="450"
|
||||||
prefHeight="450"
|
prefHeight="450"
|
||||||
spacing="12"
|
spacing="12"
|
||||||
alignment="CENTER_LEFT"
|
alignment="CENTER_LEFT">
|
||||||
accessibleRole="DIALOG">
|
|
||||||
<padding>
|
<padding>
|
||||||
<Insets topRightBottomLeft="24"/>
|
<Insets topRightBottomLeft="24"/>
|
||||||
</padding>
|
</padding>
|
||||||
|
|||||||
@@ -16,8 +16,7 @@
|
|||||||
prefWidth="450"
|
prefWidth="450"
|
||||||
prefHeight="450"
|
prefHeight="450"
|
||||||
spacing="12"
|
spacing="12"
|
||||||
alignment="TOP_CENTER"
|
alignment="TOP_CENTER">
|
||||||
accessibleRole="DIALOG">
|
|
||||||
<padding>
|
<padding>
|
||||||
<Insets topRightBottomLeft="24"/>
|
<Insets topRightBottomLeft="24"/>
|
||||||
</padding>
|
</padding>
|
||||||
|
|||||||
@@ -13,8 +13,7 @@
|
|||||||
fx:controller="org.cryptomator.ui.changepassword.ChangePasswordController"
|
fx:controller="org.cryptomator.ui.changepassword.ChangePasswordController"
|
||||||
minWidth="400"
|
minWidth="400"
|
||||||
maxWidth="400"
|
maxWidth="400"
|
||||||
spacing="12"
|
spacing="12">
|
||||||
accessibleRole="DIALOG">
|
|
||||||
<padding>
|
<padding>
|
||||||
<Insets topRightBottomLeft="12"/>
|
<Insets topRightBottomLeft="12"/>
|
||||||
</padding>
|
</padding>
|
||||||
|
|||||||
@@ -18,8 +18,7 @@
|
|||||||
maxWidth="400"
|
maxWidth="400"
|
||||||
minHeight="145"
|
minHeight="145"
|
||||||
spacing="12"
|
spacing="12"
|
||||||
alignment="TOP_CENTER"
|
alignment="TOP_CENTER">
|
||||||
accessibleRole="DIALOG">
|
|
||||||
<padding>
|
<padding>
|
||||||
<Insets topRightBottomLeft="12"/>
|
<Insets topRightBottomLeft="12"/>
|
||||||
</padding>
|
</padding>
|
||||||
|
|||||||
@@ -15,8 +15,7 @@
|
|||||||
maxWidth="400"
|
maxWidth="400"
|
||||||
minHeight="145"
|
minHeight="145"
|
||||||
spacing="12"
|
spacing="12"
|
||||||
alignment="TOP_CENTER"
|
alignment="TOP_CENTER">
|
||||||
accessibleRole="DIALOG">
|
|
||||||
<padding>
|
<padding>
|
||||||
<Insets topRightBottomLeft="12"/>
|
<Insets topRightBottomLeft="12"/>
|
||||||
</padding>
|
</padding>
|
||||||
|
|||||||
@@ -19,8 +19,7 @@
|
|||||||
maxWidth="400"
|
maxWidth="400"
|
||||||
minHeight="145"
|
minHeight="145"
|
||||||
spacing="12"
|
spacing="12"
|
||||||
alignment="TOP_LEFT"
|
alignment="TOP_LEFT">
|
||||||
accessibleRole="DIALOG">
|
|
||||||
<padding>
|
<padding>
|
||||||
<Insets topRightBottomLeft="12"/>
|
<Insets topRightBottomLeft="12"/>
|
||||||
</padding>
|
</padding>
|
||||||
|
|||||||
@@ -22,8 +22,7 @@
|
|||||||
minHeight="450"
|
minHeight="450"
|
||||||
prefWidth="450"
|
prefWidth="450"
|
||||||
prefHeight="450"
|
prefHeight="450"
|
||||||
spacing="12"
|
spacing="12">
|
||||||
accessibleRole="DIALOG">
|
|
||||||
<padding>
|
<padding>
|
||||||
<Insets topRightBottomLeft="24"/>
|
<Insets topRightBottomLeft="24"/>
|
||||||
</padding>
|
</padding>
|
||||||
|
|||||||
@@ -21,8 +21,7 @@
|
|||||||
maxWidth="400"
|
maxWidth="400"
|
||||||
minHeight="145"
|
minHeight="145"
|
||||||
spacing="12"
|
spacing="12"
|
||||||
alignment="TOP_LEFT"
|
alignment="TOP_LEFT">
|
||||||
accessibleRole="DIALOG">
|
|
||||||
<padding>
|
<padding>
|
||||||
<Insets topRightBottomLeft="12"/>
|
<Insets topRightBottomLeft="12"/>
|
||||||
</padding>
|
</padding>
|
||||||
|
|||||||
@@ -18,8 +18,7 @@
|
|||||||
maxWidth="400"
|
maxWidth="400"
|
||||||
minHeight="145"
|
minHeight="145"
|
||||||
spacing="12"
|
spacing="12"
|
||||||
alignment="TOP_LEFT"
|
alignment="TOP_LEFT">
|
||||||
accessibleRole="DIALOG">
|
|
||||||
<padding>
|
<padding>
|
||||||
<Insets topRightBottomLeft="12"/>
|
<Insets topRightBottomLeft="12"/>
|
||||||
</padding>
|
</padding>
|
||||||
|
|||||||
@@ -20,8 +20,7 @@
|
|||||||
maxWidth="400"
|
maxWidth="400"
|
||||||
minHeight="145"
|
minHeight="145"
|
||||||
spacing="12"
|
spacing="12"
|
||||||
alignment="TOP_LEFT"
|
alignment="TOP_LEFT">
|
||||||
accessibleRole="DIALOG">
|
|
||||||
<padding>
|
<padding>
|
||||||
<Insets topRightBottomLeft="12"/>
|
<Insets topRightBottomLeft="12"/>
|
||||||
</padding>
|
</padding>
|
||||||
|
|||||||
@@ -18,8 +18,7 @@
|
|||||||
maxWidth="400"
|
maxWidth="400"
|
||||||
minHeight="145"
|
minHeight="145"
|
||||||
spacing="12"
|
spacing="12"
|
||||||
alignment="TOP_LEFT"
|
alignment="TOP_LEFT">
|
||||||
accessibleRole="DIALOG">
|
|
||||||
<padding>
|
<padding>
|
||||||
<Insets topRightBottomLeft="12"/>
|
<Insets topRightBottomLeft="12"/>
|
||||||
</padding>
|
</padding>
|
||||||
|
|||||||
@@ -20,8 +20,7 @@
|
|||||||
maxWidth="400"
|
maxWidth="400"
|
||||||
minHeight="145"
|
minHeight="145"
|
||||||
spacing="12"
|
spacing="12"
|
||||||
alignment="TOP_LEFT"
|
alignment="TOP_LEFT">
|
||||||
accessibleRole="DIALOG">
|
|
||||||
<padding>
|
<padding>
|
||||||
<Insets topRightBottomLeft="12"/>
|
<Insets topRightBottomLeft="12"/>
|
||||||
</padding>
|
</padding>
|
||||||
|
|||||||
@@ -18,8 +18,7 @@
|
|||||||
maxWidth="400"
|
maxWidth="400"
|
||||||
minHeight="145"
|
minHeight="145"
|
||||||
spacing="12"
|
spacing="12"
|
||||||
alignment="TOP_LEFT"
|
alignment="TOP_LEFT">
|
||||||
accessibleRole="DIALOG">
|
|
||||||
<padding>
|
<padding>
|
||||||
<Insets topRightBottomLeft="12"/>
|
<Insets topRightBottomLeft="12"/>
|
||||||
</padding>
|
</padding>
|
||||||
|
|||||||
@@ -20,8 +20,7 @@
|
|||||||
maxWidth="400"
|
maxWidth="400"
|
||||||
minHeight="145"
|
minHeight="145"
|
||||||
spacing="12"
|
spacing="12"
|
||||||
alignment="TOP_LEFT"
|
alignment="TOP_LEFT">
|
||||||
accessibleRole="DIALOG">
|
|
||||||
<padding>
|
<padding>
|
||||||
<Insets topRightBottomLeft="12"/>
|
<Insets topRightBottomLeft="12"/>
|
||||||
</padding>
|
</padding>
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user