Compare commits

..
Author SHA1 Message Date
Armin Schrenk 1dab85d265 Merge branch 'develop' into release/1.19.0 2026-02-18 16:25:04 +01:00
Armin Schrenk 423752e720 [skip ci] update changelog 2026-02-18 16:22:31 +01:00
CryptobotandGitHub 4efcec7e93 New Crowdin updates (#4041)
New translations strings.properties

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

[ci skip]
2026-02-18 15:56:30 +01:00
Armin Schrenk 619d981ded [skip ci] Update README 2026-02-18 15:46:47 +01:00
mindmonkandGitHub 72d93e943b fix text wrapping in ResetPasswordDialog (#4123) 2026-02-18 15:43:50 +01:00
Armin SchrenkandGitHub f07523267d Bump javafx to version 25.0.2 (#4145) 2026-02-18 15:42:51 +01:00
Armin Schrenk 5409470750 update wix 2026-02-18 15:27:36 +01:00
Armin Schrenk 70b7f39bcc revert 5ab12c1b1a for windows build 2026-02-18 15:16:39 +01:00
Armin Schrenk 5ab12c1b1a Update to latest JDK 25 2026-02-18 11:49:13 +01:00
Armin Schrenk 0ac63e7aba Closes #4136 2026-02-18 11:26:42 +01:00
Armin Schrenk ac6f34fe17 reorder changelog 2026-02-18 11:15:46 +01:00
Armin Schrenk dba3de230b Update dependencies
* 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
2026-02-18 11:15:00 +01:00
Armin Schrenk e11d42bb07 update IDE file 2026-02-18 11:07:18 +01:00
Jan-Peter Klein 171d5d5a4c Fixes #4141 2026-02-18 10:55:49 +01:00
Armin Schrenk b86d8ca790 [skip ci] update changelog 2026-02-17 15:30:20 +01:00
Armin Schrenk 74fc77ab8d fix pom inconsistency 2026-02-17 15:21:16 +01:00
Armin Schrenk 044dbcb11f Update cryptofs to version 2.10.0-beta3 2026-02-17 15:13:46 +01:00
Armin Schrenk 1b243bb725 suppress logging of expected exception 2026-02-17 15:12:25 +01:00
Armin SchrenkandGitHub f21cb90e7d Merge pull request #4025 from purejava/new-secret-service
New keychain backend SecretService for Linux
2026-02-17 13:16:06 +01:00
Armin SchrenkandGitHub 1e8f272f6a Merge pull request #4143 from cryptomator/dependabot/maven/java-production-dependencies-d98826387a
Bump the java-production-dependencies group across 1 directory with 11 updates
2026-02-17 13:15:07 +01:00
Armin Schrenk 5c1f8e7576 update IDE file 2026-02-17 12:46:19 +01:00
Armin Schrenk bc0bb38e4c remove dagger formatting due to compile error 2026-02-17 12:45:46 +01:00
Armin SchrenkandGitHub b9b02acbe5 Merge pull request #4134 from cryptomator/feature/javafx-color-scheme-change
Feature: Use JavaFX built ins to adapt to OS color scheme
2026-02-17 10:36:23 +01:00
Armin Schrenk e53598cfce update azure signing to stable version 2026-02-16 17:06:00 +01:00
Armin Schrenk a79fd63634 [skip ci] update changelog 2026-02-16 16:15:05 +01:00
f753ddc9be Apply suggestions from code review
Co-authored-by: Sebastian Stenzel <overheadhunter@users.noreply.github.com>
2026-02-16 16:05:26 +01:00
Armin Schrenk 158b454b0d fix NPE in EventualLogger 2026-02-16 12:45:57 +01:00
Armin Schrenk 9e6bd913cb refactor FxApplicationStyle
use pattern (removeOldListeners, addNewListerner, applyTheme)
2026-02-16 12:37:46 +01:00
Armin Schrenk 83ef9d06d9 simplify JfxUiAppearanceProvider
and move loading of appearance service into the fx app
2026-02-16 11:55:03 +01:00
Armin Schrenk cf0052b4f5 revert lambda processing 2026-02-16 11:07:04 +01:00
Armin Schrenk 0b4d86768a Closes #4088 2026-02-16 10:13:21 +01:00
dependabot[bot]andGitHub a77e90738a Bump the java-production-dependencies group across 1 directory with 11 updates
Bumps the java-production-dependencies group with 11 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [org.cryptomator:cryptolib](https://github.com/cryptomator/cryptolib) | `2.2.1` | `2.2.2` |
| [org.cryptomator:fuse-nio-adapter](https://github.com/cryptomator/fuse-nio-adapter) | `5.1.0` | `6.0.0` |
| [ch.qos.logback:logback-core](https://github.com/qos-ch/logback) | `1.5.19` | `1.5.31` |
| [ch.qos.logback:logback-classic](https://github.com/qos-ch/logback) | `1.5.19` | `1.5.31` |
| org.apache.commons:commons-lang3 | `3.19.0` | `3.20.0` |
| [com.fasterxml.jackson.core:jackson-databind](https://github.com/FasterXML/jackson) | `2.20.0` | `2.21.0` |
| com.fasterxml.jackson.datatype:jackson-datatype-jsr310 | `2.20.0` | `2.21.0` |
| [com.google.dagger:dagger](https://github.com/google/dagger) | `2.57.2` | `2.59.1` |
| [com.google.dagger:dagger-compiler](https://github.com/google/dagger) | `2.57.2` | `2.59.1` |
| [com.github.ben-manes.caffeine:caffeine](https://github.com/ben-manes/caffeine) | `3.2.2` | `3.2.3` |
| [org.cryptomator:integrations-linux](https://github.com/cryptomator/integrations-linux) | `1.7.0-beta3` | `1.7.0-beta4` |



Updates `org.cryptomator:cryptolib` from 2.2.1 to 2.2.2
- [Release notes](https://github.com/cryptomator/cryptolib/releases)
- [Changelog](https://github.com/cryptomator/cryptolib/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/cryptomator/cryptolib/compare/2.2.1...2.2.2)

Updates `org.cryptomator:fuse-nio-adapter` from 5.1.0 to 6.0.0
- [Release notes](https://github.com/cryptomator/fuse-nio-adapter/releases)
- [Changelog](https://github.com/cryptomator/fuse-nio-adapter/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/cryptomator/fuse-nio-adapter/compare/5.1.0...6.0.0)

Updates `ch.qos.logback:logback-core` from 1.5.19 to 1.5.31
- [Release notes](https://github.com/qos-ch/logback/releases)
- [Commits](https://github.com/qos-ch/logback/compare/v_1.5.19...v_1.5.31)

Updates `ch.qos.logback:logback-classic` from 1.5.19 to 1.5.31
- [Release notes](https://github.com/qos-ch/logback/releases)
- [Commits](https://github.com/qos-ch/logback/compare/v_1.5.19...v_1.5.31)

Updates `ch.qos.logback:logback-classic` from 1.5.19 to 1.5.31
- [Release notes](https://github.com/qos-ch/logback/releases)
- [Commits](https://github.com/qos-ch/logback/compare/v_1.5.19...v_1.5.31)

Updates `org.apache.commons:commons-lang3` from 3.19.0 to 3.20.0

Updates `com.fasterxml.jackson.core:jackson-databind` from 2.20.0 to 2.21.0
- [Commits](https://github.com/FasterXML/jackson/commits)

Updates `com.fasterxml.jackson.datatype:jackson-datatype-jsr310` from 2.20.0 to 2.21.0

Updates `com.fasterxml.jackson.datatype:jackson-datatype-jsr310` from 2.20.0 to 2.21.0

Updates `com.google.dagger:dagger` from 2.57.2 to 2.59.1
- [Release notes](https://github.com/google/dagger/releases)
- [Changelog](https://github.com/google/dagger/blob/master/CHANGELOG.md)
- [Commits](https://github.com/google/dagger/compare/dagger-2.57.2...dagger-2.59.1)

Updates `com.google.dagger:dagger-compiler` from 2.57.2 to 2.59.1
- [Release notes](https://github.com/google/dagger/releases)
- [Changelog](https://github.com/google/dagger/blob/master/CHANGELOG.md)
- [Commits](https://github.com/google/dagger/compare/dagger-2.57.2...dagger-2.59.1)

Updates `com.github.ben-manes.caffeine:caffeine` from 3.2.2 to 3.2.3
- [Release notes](https://github.com/ben-manes/caffeine/releases)
- [Commits](https://github.com/ben-manes/caffeine/compare/v3.2.2...v3.2.3)

Updates `com.google.dagger:dagger-compiler` from 2.57.2 to 2.59.1
- [Release notes](https://github.com/google/dagger/releases)
- [Changelog](https://github.com/google/dagger/blob/master/CHANGELOG.md)
- [Commits](https://github.com/google/dagger/compare/dagger-2.57.2...dagger-2.59.1)

Updates `org.cryptomator:integrations-linux` from 1.7.0-beta3 to 1.7.0-beta4
- [Release notes](https://github.com/cryptomator/integrations-linux/releases)
- [Changelog](https://github.com/cryptomator/integrations-linux/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/cryptomator/integrations-linux/compare/1.7.0-beta3...1.7.0-beta4)

---
updated-dependencies:
- dependency-name: org.cryptomator:cryptolib
  dependency-version: 2.2.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: java-production-dependencies
- dependency-name: org.cryptomator:fuse-nio-adapter
  dependency-version: 6.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: java-production-dependencies
- dependency-name: ch.qos.logback:logback-core
  dependency-version: 1.5.31
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: java-production-dependencies
- dependency-name: ch.qos.logback:logback-classic
  dependency-version: 1.5.31
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: java-production-dependencies
- dependency-name: ch.qos.logback:logback-classic
  dependency-version: 1.5.31
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: java-production-dependencies
- dependency-name: org.apache.commons:commons-lang3
  dependency-version: 3.20.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: java-production-dependencies
- dependency-name: com.fasterxml.jackson.core:jackson-databind
  dependency-version: 2.21.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: java-production-dependencies
- dependency-name: com.fasterxml.jackson.datatype:jackson-datatype-jsr310
  dependency-version: 2.21.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: java-production-dependencies
- dependency-name: com.fasterxml.jackson.datatype:jackson-datatype-jsr310
  dependency-version: 2.21.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: java-production-dependencies
- dependency-name: com.google.dagger:dagger
  dependency-version: 2.59.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: java-production-dependencies
- dependency-name: com.google.dagger:dagger-compiler
  dependency-version: 2.59.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: java-production-dependencies
- dependency-name: com.github.ben-manes.caffeine:caffeine
  dependency-version: 3.2.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: java-production-dependencies
- dependency-name: com.google.dagger:dagger-compiler
  dependency-version: 2.59.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: java-production-dependencies
- dependency-name: org.cryptomator:integrations-linux
  dependency-version: 1.7.0-beta4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: java-production-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-16 06:06:54 +00:00
mindmonkandGitHub 0bec741c2b Merge pull request #4120 from cryptomator/feature/disable-password-tab-if-masterkey-missing
Disable recovery key actions in Vault Password options when masterkey is missing
2026-02-12 18:08:52 +01:00
Armin SchrenkandGitHub af43aeca15 Merge branch 'develop' into feature/javafx-color-scheme-change 2026-02-12 10:18:32 +01:00
Armin Schrenk 1629eae5d3 [skip ci] update changelog 2026-02-11 15:55:34 +01:00
Armin Schrenk 99898b74fb minor cleanup 2026-02-11 15:55:19 +01:00
Armin SchrenkandGitHub 327d6065e9 Merge pull request #4105 from cryptomator/feature/admin-properties
Feature: Admin Config
2026-02-11 15:25:31 +01:00
Armin Schrenk 2a5ef5d999 log inconsistent state 2026-02-11 15:21:55 +01:00
Armin Schrenk 34e5d19a04 prevent resource leak 2026-02-11 15:16:11 +01:00
Armin Schrenk 33851a8559 Refactor admin props
* rename class to AdminPropertiesFactory
* rename factory method to "create"
* remove side effects from methods
* returned properties default to system properties
2026-02-11 15:12:52 +01:00
Armin Schrenk fb54d96997 fix wrong method delegation 2026-02-11 14:49:56 +01:00
Armin Schrenk cff47b1c73 wrap system properties instead of direct modification 2026-02-11 14:36:55 +01:00
Armin Schrenk 5db05d8bc7 Apply suggestions from codereview 2026-02-11 14:33:01 +01:00
Armin Schrenk b85780eae9 Disable JavaFX based UiAppearanceProvider for macOS 2026-02-11 12:22:22 +01:00
Ralph Plawetzki bdfd22c483 Partially reverts https://github.com/cryptomator/cryptomator/commit/dd1af8cd783589e8c8b06e7c4881195e10a67815
Not needed anymore, see https://github.com/cryptomator/integrations-linux/pull/125#issuecomment-3876060158
2026-02-11 06:07:01 +01:00
Armin Schrenk e3433cb312 Refactor FxApplicationStyle class 2026-02-10 18:17:09 +01:00
Armin Schrenk 46d1d605ad refactor JfxUiAppearanceProvider class
* use delegate pattern for initialization
* add logging
2026-02-10 18:01:36 +01:00
Armin Schrenk a4eadd4817 remove theme change restrictions 2026-02-10 17:58:29 +01:00
Armin Schrenk c6717bd4e1 Rely on javafx to change color theme 2026-02-09 17:48:23 +01:00
Armin Schrenk 53f368108a Rename jvm property and actual config file 2026-02-09 16:54:04 +01:00
Armin Schrenk 5e52811c74 Remove hard coded default locations for admin config 2026-02-09 16:49:12 +01:00
Armin Schrenk cad7b45808 Refactor to first check system property cryptomator.adminConfig for config path 2026-02-09 16:16:26 +01:00
Armin Schrenk a057bf6f70 Merge branch 'develop' into feature/admin-properties 2026-02-09 15:03:06 +01:00
Armin Schrenk 4cf11cf293 [skip ci] update changelog 2026-02-09 14:56:37 +01:00
Armin SchrenkandGitHub 2523609996 disable loading of user defined config for windows msi (#4132) 2026-02-09 14:49:07 +01:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
80276ee992 Bump the github-actions group across 1 directory with 8 updates (#4124)
Bumps the github-actions group with 8 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [actions/checkout](https://github.com/actions/checkout) | `6.0.1` | `6.0.2` |
| [actions/setup-java](https://github.com/actions/setup-java) | `5.1.0` | `5.2.0` |
| [actions/upload-artifact](https://github.com/actions/upload-artifact) | `5.0.0` | `6.0.0` |
| [actions/download-artifact](https://github.com/actions/download-artifact) | `6.0.0` | `7.0.0` |
| [actions/cache](https://github.com/actions/cache) | `4.3.0` | `5.0.3` |
| [skymatic/workflows/.github/workflows/run-dependency-check.yml](https://github.com/skymatic/workflows) | `3.0.1` | `3.0.2` |
| [fjogeleit/http-request-action](https://github.com/fjogeleit/http-request-action) | `1.16.6` | `2.0.0` |
| [skymatic/workflows](https://github.com/skymatic/workflows) | `3.0.1` | `3.0.2` |



Updates `actions/checkout` from 6.0.1 to 6.0.2
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/8e8c483db84b4bee98b60c0593521ed34d9990e8...de0fac2e4500dabe0009e67214ff5f5447ce83dd)

Updates `actions/setup-java` from 5.1.0 to 5.2.0
- [Release notes](https://github.com/actions/setup-java/releases)
- [Commits](https://github.com/actions/setup-java/compare/f2beeb24e141e01a676f977032f5a29d81c9e27e...be666c2fcd27ec809703dec50e508c2fdc7f6654)

Updates `actions/upload-artifact` from 5.0.0 to 6.0.0
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/330a01c490aca151604b8cf639adc76d48f6c5d4...b7c566a772e6b6bfb58ed0dc250532a479d7789f)

Updates `actions/download-artifact` from 6.0.0 to 7.0.0
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/018cc2cf5baa6db3ef3c5f8a56943fffe632ef53...37930b1c2abaa49bbe596cd826c3c89aef350131)

Updates `actions/cache` from 4.3.0 to 5.0.3
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/0057852bfaa89a56745cba8c7296529d2fc39830...cdf6c1fa76f9f475f3d7449005a359c84ca0f306)

Updates `skymatic/workflows/.github/workflows/run-dependency-check.yml` from 3.0.1 to 3.0.2
- [Release notes](https://github.com/skymatic/workflows/releases)
- [Commits](https://github.com/skymatic/workflows/compare/1074588008ae3326a2221ea451783280518f0366...2d0c27a7b04c605afe1ca85e37c0e86517defcc9)

Updates `fjogeleit/http-request-action` from 1.16.6 to 2.0.0
- [Release notes](https://github.com/fjogeleit/http-request-action/releases)
- [Changelog](https://github.com/fjogeleit/http-request-action/blob/main/RELEASE.md)
- [Commits](https://github.com/fjogeleit/http-request-action/compare/c0b95d02a088b47c1f2f4db04fd8af8bd19eee54...551353b829c3646756b2ec2b3694f819d7957495)

Updates `skymatic/workflows` from 3.0.1 to 3.0.2
- [Release notes](https://github.com/skymatic/workflows/releases)
- [Commits](https://github.com/skymatic/workflows/compare/1074588008ae3326a2221ea451783280518f0366...2d0c27a7b04c605afe1ca85e37c0e86517defcc9)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 6.0.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
- dependency-name: actions/setup-java
  dependency-version: 5.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
- dependency-name: actions/upload-artifact
  dependency-version: 6.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
- dependency-name: actions/download-artifact
  dependency-version: 7.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
- dependency-name: actions/cache
  dependency-version: 5.0.3
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
- dependency-name: skymatic/workflows/.github/workflows/run-dependency-check.yml
  dependency-version: 3.0.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
- dependency-name: fjogeleit/http-request-action
  dependency-version: 2.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
- dependency-name: skymatic/workflows
  dependency-version: 3.0.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-09 09:27:49 +01:00
Ralph Plawetzki 561432bc98 Revert "Make SecretServiceKeychainAccess the default selection"
This reverts commit 9a74194391.
Users decide when to migrate.
2026-02-05 08:15:10 +01:00
Ralph Plawetzki cd0a640a36 Enable migrating KeychainEntries on Linux as well 2026-02-05 07:09:38 +01:00
Armin SchrenkandGitHub a7b8541912 Update Slack webhook URL secret in workflow 2026-01-30 15:27:31 +01:00
Jan-Peter Klein d4382f3130 remove docTooltip 2026-01-28 18:40:56 +01:00
Jan-Peter Klein 2983745be5 remove docs link 2026-01-28 18:20:18 +01:00
Armin Schrenk 77983fe00a simplify EventualLogger init 2026-01-28 17:44:48 +01:00
Armin Schrenk a4836f6528 cleanup 2026-01-28 17:36:52 +01:00
Armin Schrenk e9b3b505a8 apply suggestions from code review 2026-01-28 17:35:34 +01:00
Armin Schrenk 19c9eada9d check first the filesize before opening a Reader to the config file 2026-01-28 17:32:10 +01:00
Jan-Peter Klein 2a5bce2c5c disable password tab when masterkey.file is missing 2026-01-27 17:42:04 +01:00
mindmonkandGitHub 9ee81a0e35 Merge pull request #4106 from cryptomator/feature/move-recover-io-tasks-to-background
Move recovery I/O to background thread
2026-01-26 13:30:39 +01:00
Jan-Peter Klein 8b05ae0a54 dedup createTask 2026-01-23 16:09:06 +01:00
Jan-Peter Klein aa898c634f refactor recovery restore to sync logic with async task wrapper for testability 2026-01-23 13:57:38 +01:00
Armin Schrenk efbd107fb5 increase null safety 2026-01-21 18:09:26 +01:00
Armin Schrenk 300cac5441 don't forget log markers 2026-01-21 16:36:56 +01:00
Armin Schrenk b651b9ac26 config file can be exactly the max size 2026-01-21 16:08:00 +01:00
Armin Schrenk 29e76e7f93 keep throwables in EventualLogger 2026-01-21 16:07:17 +01:00
Armin Schrenk 5cac6b8114 also adjust distribution 2026-01-21 15:55:04 +01:00
Armin Schrenk 35c2141fd6 cleanup 2026-01-21 15:34:34 +01:00
Armin Schrenk b00c81c20a use "cryptomator.config" for config file 2026-01-21 15:34:24 +01:00
Armin Schrenk 7ee0606306 adjust unit tests 2026-01-21 15:34:08 +01:00
Armin Schrenk 046372f95b refactored BufferedLog
* rename to EventualLogger
* adhere to slf4j API
* ensure single instance
2026-01-21 15:33:26 +01:00
Armin Schrenk c198adaf3f switch back to properties 2026-01-21 11:53:31 +01:00
Armin Schrenk d53f0880ca add test for AdminPropertiesSetter 2026-01-15 18:06:24 +01:00
Armin Schrenk 088b177c0e Ensure that null map is also logged 2026-01-15 15:11:46 +01:00
Armin Schrenk 287ab4e792 [skip ci] Update changelog 2026-01-15 15:11:12 +01:00
Armin SchrenkandGitHub 0e9cad5b09 Merge pull request #4103 from cryptomator/feature/basic-accessibility
Feature: Improve accessibility for core functionality
2026-01-15 10:44:16 +01:00
Armin Schrenk a0c9caeb21 [skip ci] update changelog 2026-01-14 17:57:24 +01:00
Armin Schrenk f620c6685a apply suggestions from AI review 2026-01-14 17:53:07 +01:00
Armin Schrenk 61be8c449c fixed flush does not clear BufferedLog 2026-01-14 17:39:49 +01:00
Armin Schrenk 43343b9954 fix wrong Linux path 2026-01-14 17:36:07 +01:00
Armin Schrenk 460b7e6225 [skip ci] update changelog 2026-01-14 17:33:45 +01:00
Armin Schrenk e2430bfb22 add null check 2026-01-14 17:29:56 +01:00
Armin Schrenk ac7c9c2165 use a bracket to "describe" the vault state 2026-01-14 17:28:20 +01:00
Jan-Peter Klein efd73e0d3e move recovery IO operations to background 2026-01-14 17:14:23 +01:00
Armin Schrenk b441803462 also adjust wix installer to new config format 2026-01-14 16:28:48 +01:00
Armin Schrenk 42b06aa556 Switch to JSON as config format
Java Properties require ISO 8859-1 character encoding, leading to manual edits of file.
2026-01-14 14:12:28 +01:00
Armin Schrenk b1c21501a6 Add dummy admin properties file in Windows installer 2026-01-13 18:40:53 +01:00
Armin Schrenk 45633837e0 only allow overwriting a subset of JVM properties 2026-01-13 17:26:48 +01:00
Armin Schrenk b23bd0b27a Implement logic to overwrite system properties set in app internal config file 2026-01-13 13:14:40 +01:00
Armin Schrenk b3f3faf4ee add DIALOG role to more dialogs 2026-01-13 11:02:01 +01:00
Armin Schrenk 33f26bf804 Refactor notificationbar
* rename to InfoBar
* replace closeButton text with graphic and add accessibilityText
* use common base class for styling and use CSS lookup for variants
2026-01-12 23:31:37 +01:00
Armin Schrenk a06accb80f add accessibletext to vault storage location 2026-01-12 23:15:40 +01:00
Armin Schrenk a50e372f05 add correct accessible role to dialogs 2026-01-12 23:14:09 +01:00
Armin Schrenk 06726303fb add proper accessibility text for vault list 2026-01-12 23:13:15 +01:00
Armin Schrenk 11c86f7287 impl idea 2026-01-12 11:59:17 +01:00
mindmonkandGitHub 8e68a62ab0 Merge pull request #4081 from cryptomator/feature/hub-vault-archived-dialog
Feature: Show dedicated “Archived Vault” screen on unlock when Hub returns 410
2026-01-06 11:20:29 +01:00
Jan-Peter Klein 787d0b8e12 code cleanup 2026-01-05 14:00:20 +01:00
Jan-Peter Klein ba765f7a69 code cleanup 2026-01-05 13:31:45 +01:00
Jan-Peter Klein e9d7e631c7 fix typo 2026-01-05 13:27:50 +01:00
Jan-Peter Klein 88acbc8ed7 fix typo 2026-01-05 13:22:01 +01:00
Jan-Peter Klein e84a73b9c3 use SimpleDialog 2026-01-05 13:17:10 +01:00
Jan-Peter Klein 2324ddad8b update changelog 2026-01-05 11:53:51 +01:00
Jan-Peter Klein 04da2504de Merge branch 'develop' into feature/hub-vault-archived-dialog 2026-01-05 11:28:08 +01:00
Armin Schrenk ad240eb18b Merge branch 'develop' into release/1.19.0
# Conflicts:
#	pom.xml
2025-12-30 12:40:06 +01:00
Armin Schrenk 8105dbc236 Closes #4058 2025-12-30 12:31:45 +01:00
Armin Schrenk ceed70c314 [skip ci] update changelog 2025-12-29 16:59:01 +01:00
Jan-Peter Klein 760e260eba show archived vault dialog on unlock when Hub returns 410 2025-12-17 09:56:56 +01:00
Sebastian Stenzel 04bdb2d8c4 fix mocked update check 2025-11-24 20:58:57 +01:00
Sebastian Stenzel f32d24c1c0 Merge branch 'develop' into release/1.19.0 2025-11-24 20:58:25 +01:00
Sebastian Stenzel 3f06460667 bump version 2025-11-24 14:50:19 +01:00
Ralph Plawetzki 9a74194391 Make SecretServiceKeychainAccess the default selection 2025-10-27 05:33:35 +01:00
169 changed files with 2920 additions and 695 deletions
+2 -2
View File
@@ -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/trusted-signing-action@fc390cf8ed0f14e248a542af1d838388a47c7a7c # v0.5.10 uses: azure/artifact-signing-action@87c2e83e6868da99d3380aa309851b32ed9a8346 # v1.1.0
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 }}
trusted-signing-account-name: cryptomatorSigning 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
+11 -11
View File
@@ -19,7 +19,7 @@ on:
env: env:
JAVA_DIST: 'temurin' JAVA_DIST: 'temurin'
JAVA_VERSION: '25.0.1+8.0.LTS' JAVA_VERSION: '25.0.2+10.0.LTS'
jobs: jobs:
get-version: get-version:
@@ -37,16 +37,16 @@ jobs:
include: include:
- os: ubuntu-latest - os: ubuntu-latest
appimage-suffix: x86_64 appimage-suffix: x86_64
openjfx-url: 'https://download2.gluonhq.com/openjfx/25/openjfx-25_linux-x64_bin-jmods.zip' openjfx-url: 'https://download2.gluonhq.com/openjfx/25.0.2/openjfx-25.0.2_linux-x64_bin-jmods.zip'
openjfx-sha: '96e520f48610d8ffb94ca30face1f11ffe8a977ddc1c4ff80b1a9e9f048bd94e' openjfx-sha: 'e0a9c29d8cf3af9b8b48848b43f87b5785bc107c53a951b19668ce05842bba1b'
- os: ubuntu-24.04-arm - os: ubuntu-24.04-arm
appimage-suffix: aarch64 appimage-suffix: aarch64
openjfx-url: 'https://download2.gluonhq.com/openjfx/25/openjfx-25_linux-aarch64_bin-jmods.zip' openjfx-url: 'https://download2.gluonhq.com/openjfx/25.0.2/openjfx-25.0.2_linux-aarch64_bin-jmods.zip'
openjfx-sha: '9ad4ca7b769ca4ee6419f1e99143dd6ff812f8be4fddb46a7d7cacbeea148af4' openjfx-sha: 'c3408f818693cce09e59829a8e862a82c7695fdfcd585c41cfd527f5fc3fe646'
steps: steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup Java - name: Setup Java
uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # v5.1.0 uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with: with:
distribution: ${{ env.JAVA_DIST }} distribution: ${{ env.JAVA_DIST }}
java-version: ${{ env.JAVA_VERSION }} java-version: ${{ env.JAVA_VERSION }}
@@ -122,8 +122,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=\"/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\""
@@ -175,7 +175,7 @@ jobs:
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@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with: with:
name: appimage-${{ matrix.appimage-suffix }} name: appimage-${{ matrix.appimage-suffix }}
path: | path: |
@@ -201,7 +201,7 @@ jobs:
if: github.event_name == 'release' && needs.get-version.outputs.versionType == 'stable' if: github.event_name == 'release' && needs.get-version.outputs.versionType == 'stable'
steps: steps:
- name: Download AppImages - name: Download AppImages
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with: with:
path: downloads/ path: downloads/
merge-multiple: true merge-multiple: true
@@ -212,7 +212,7 @@ jobs:
echo "x64-sha256sum=${X64_SHA256}" >> "$GITHUB_OUTPUT" echo "x64-sha256sum=${X64_SHA256}" >> "$GITHUB_OUTPUT"
AARCH64_SHA256=$(sha256sum downloads/cryptomator-*-aarch64.AppImage | cut -d ' ' -f1) AARCH64_SHA256=$(sha256sum downloads/cryptomator-*-aarch64.AppImage | cut -d ' ' -f1)
echo "aarch64-sha256sum=${AARCH64_SHA256}" >> "$GITHUB_OUTPUT" echo "aarch64-sha256sum=${AARCH64_SHA256}" >> "$GITHUB_OUTPUT"
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with: with:
repository: 'cryptomator/aur-bin' repository: 'cryptomator/aur-bin'
token: ${{ secrets.CRYPTOBOT_PR_TOKEN }} token: ${{ secrets.CRYPTOBOT_PR_TOKEN }}
+1 -1
View File
@@ -48,7 +48,7 @@ jobs:
env: env:
AUR_PR_URL: tbd AUR_PR_URL: tbd
steps: steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with: with:
repository: 'cryptomator/aur' repository: 'cryptomator/aur'
token: ${{ secrets.CRYPTOBOT_PR_TOKEN }} token: ${{ secrets.CRYPTOBOT_PR_TOKEN }}
+3 -3
View File
@@ -51,7 +51,7 @@ jobs:
- name: Download file - name: Download file
run: curl "${INPUT_URL}" -L -o "${{steps.extractName.outputs.fileName}}" --fail-with-body run: curl "${INPUT_URL}" -L -o "${{steps.extractName.outputs.fileName}}" --fail-with-body
- name: Upload artifact - name: Upload artifact
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.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@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.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@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with: with:
name: ${{ needs.download-file.outputs.fileName }} name: ${{ needs.download-file.outputs.fileName }}
path: upload path: upload
+3 -3
View File
@@ -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@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # v5.1.0 - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.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@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
with: with:
path: ~/.sonar/cache path: ~/.sonar/cache
key: ${{ runner.os }}-sonar key: ${{ runner.os }}-sonar
+1 -1
View File
@@ -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@f2beeb24e141e01a676f977032f5a29d81c9e27e # v5.1.0 uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with: with:
java-version: ${{ env.JDK_MAJOR_VERSION}} java-version: ${{ env.JDK_MAJOR_VERSION}}
distribution: ${{ env.JDK_VENDOR }} distribution: ${{ env.JDK_VENDOR }}
+8 -8
View File
@@ -23,12 +23,12 @@ on:
env: env:
JAVA_DIST: 'temurin' JAVA_DIST: 'temurin'
JAVA_VERSION: '25.0.1+8.0.LTS' JAVA_VERSION: '25.0.2+10.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/openjfx-25_linux-x64_bin-jmods.zip' OPENJFX_JMODS_AMD64: 'https://download2.gluonhq.com/openjfx/25.0.2/openjfx-25.0.2_linux-x64_bin-jmods.zip'
OPENJFX_JMODS_AMD64_HASH: '96e520f48610d8ffb94ca30face1f11ffe8a977ddc1c4ff80b1a9e9f048bd94e' OPENJFX_JMODS_AMD64_HASH: 'e0a9c29d8cf3af9b8b48848b43f87b5785bc107c53a951b19668ce05842bba1b'
OPENJFX_JMODS_AARCH64: 'https://download2.gluonhq.com/openjfx/25/openjfx-25_linux-aarch64_bin-jmods.zip' OPENJFX_JMODS_AARCH64: 'https://download2.gluonhq.com/openjfx/25.0.2/openjfx-25.0.2_linux-aarch64_bin-jmods.zip'
OPENJFX_JMODS_AARCH64_HASH: '9ad4ca7b769ca4ee6419f1e99143dd6ff812f8be4fddb46a7d7cacbeea148af4' OPENJFX_JMODS_AARCH64_HASH: 'c3408f818693cce09e59829a8e862a82c7695fdfcd585c41cfd527f5fc3fe646'
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@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- 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@f2beeb24e141e01a676f977032f5a29d81c9e27e # v5.1.0 uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with: with:
distribution: ${{ env.JAVA_DIST }} distribution: ${{ env.JAVA_DIST }}
java-version: ${{ env.JAVA_VERSION }} java-version: ${{ env.JAVA_VERSION }}
@@ -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@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with: with:
name: linux-deb-package name: linux-deb-package
path: | path: |
+2 -2
View File
@@ -7,7 +7,7 @@ on:
jobs: jobs:
check-dependencies: check-dependencies:
uses: skymatic/workflows/.github/workflows/run-dependency-check.yml@1074588008ae3326a2221ea451783280518f0366 # v3.0.1 uses: skymatic/workflows/.github/workflows/run-dependency-check.yml@957d3c2c08c56855fdac41e5afb9a7aca8c30dd9 # v3.0.3
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_URL }} slack-webhook-url: ${{ secrets.SLACK_WEBHOOK_CRYPTOMATOR_DESKTOP }}
+1 -1
View File
@@ -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@c0b95d02a088b47c1f2f4db04fd8af8bd19eee54 # v1.16.6 uses: fjogeleit/http-request-action@551353b829c3646756b2ec2b3694f819d7957495 # v2.0.0
with: with:
url: 'https://graphite-us-central1.grafana.net/metrics' url: 'https://graphite-us-central1.grafana.net/metrics'
method: 'POST' method: 'POST'
+1 -1
View File
@@ -43,7 +43,7 @@ jobs:
env: env:
FLATHUB_PR_URL: tbd FLATHUB_PR_URL: tbd
steps: steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with: with:
repository: 'flathub/org.cryptomator.Cryptomator' repository: 'flathub/org.cryptomator.Cryptomator'
token: ${{ secrets.CRYPTOBOT_PR_TOKEN }} token: ${{ secrets.CRYPTOBOT_PR_TOKEN }}
+2 -2
View File
@@ -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@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Setup Java - name: Setup Java
uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # v5.1.0 uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with: with:
distribution: ${{ env.JAVA_DIST }} distribution: ${{ env.JAVA_DIST }}
java-version: ${{ env.JAVA_VERSION }} java-version: ${{ env.JAVA_VERSION }}
+7 -7
View File
@@ -24,7 +24,7 @@ on:
env: env:
JAVA_DIST: 'temurin' JAVA_DIST: 'temurin'
JAVA_VERSION: '25.0.1+8.0.LTS' JAVA_VERSION: '25.0.2+10.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/openjfx-25_osx-x64_bin-jmods.zip' openjfx-url: 'https://download2.gluonhq.com/openjfx/25.0.2/openjfx-25.0.2_osx-x64_bin-jmods.zip'
openjfx-sha: '0eba73fb28a24c845175d16fa2f8c081c936ce6de1be9b79eb6119fa32e53d52' openjfx-sha: '0b4d8463f03901b7425d94628e4116b7078abb8dd540fbec415266fac20bda5c'
steps: steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup Java - name: Setup Java
uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # v5.1.0 uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with: with:
distribution: ${{ env.JAVA_DIST }} distribution: ${{ env.JAVA_DIST }}
java-version: ${{ env.JAVA_VERSION }} java-version: ${{ env.JAVA_VERSION }}
@@ -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\""
@@ -283,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@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with: with:
name: dmg-${{ matrix.output-suffix }} name: dmg-${{ matrix.output-suffix }}
path: | path: |
+7 -7
View File
@@ -22,7 +22,7 @@ on:
env: env:
JAVA_DIST: 'temurin' JAVA_DIST: 'temurin'
JAVA_VERSION: '25.0.1+8.0.LTS' JAVA_VERSION: '25.0.2+10.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/openjfx-25_osx-aarch64_bin-jmods.zip' openjfx-url: 'https://download2.gluonhq.com/openjfx/25.0.2/openjfx-25.0.2_osx-aarch64_bin-jmods.zip'
openjfx-sha: '13f8c0513c40c95881479fbcf0465a29a60217393fb0656f5e4eab78a9442fba' openjfx-sha: '4cd258001c75af7047005c5c891e2400ed11d24fbb09412324c0cbaf8b503c5a'
steps: steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup Java - name: Setup Java
uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # v5.1.0 uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with: with:
distribution: ${{ env.JAVA_DIST }} distribution: ${{ env.JAVA_DIST }}
java-version: ${{ env.JAVA_VERSION }} java-version: ${{ env.JAVA_VERSION }}
@@ -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\""
@@ -282,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@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with: with:
name: dmg-${{ matrix.output-suffix }} name: dmg-${{ matrix.output-suffix }}
path: | path: |
+2 -2
View File
@@ -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@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # v5.1.0 - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with: with:
distribution: ${{ env.JAVA_DIST }} distribution: ${{ env.JAVA_DIST }}
java-version: ${{ env.JAVA_VERSION }} java-version: ${{ env.JAVA_VERSION }}
+3 -3
View File
@@ -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@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup Java - name: Setup Java
uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # v5.1.0 uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with: with:
distribution: ${{ env.JAVA_DIST }} distribution: ${{ env.JAVA_DIST }}
java-version: ${{ env.JAVA_VERSION }} java-version: ${{ env.JAVA_VERSION }}
@@ -49,7 +49,7 @@ jobs:
exit 1 exit 1
fi fi
- name: Cache NVD DB - name: Cache NVD DB
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
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 }}
+27 -20
View File
@@ -22,11 +22,12 @@ on:
env: env:
OPENJFX_JMODS_AMD64: 'https://download2.gluonhq.com/openjfx/25/openjfx-25_windows-x64_bin-jmods.zip' OPENJFX_JMODS_AMD64: 'https://download2.gluonhq.com/openjfx/25.0.2/openjfx-25.0.2_windows-x64_bin-jmods.zip'
OPENJFX_JMODS_AMD64_HASH: 'c8eb9fd039b00e0020cf6c3db8ed7876bf3ee4d27860aa697a247b83b8296ae7' OPENJFX_JMODS_AMD64_HASH: '33d878dfac85590c4d77c518ed413e512d34a8479d90132b230a7ddd173576b3'
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:
@@ -51,9 +52,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@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup Java - name: Setup Java
uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # v5.1.0 uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with: with:
distribution: ${{ matrix.java-dist }} distribution: ${{ matrix.java-dist }}
java-version: ${{ matrix.java-version }} java-version: ${{ matrix.java-version }}
@@ -62,9 +63,11 @@ jobs:
cache: 'maven' cache: 'maven'
- name: Install wix and extensions - name: Install wix and extensions
run: | run: |
dotnet tool install --global wix --version 6.0.0 dotnet tool install --global wix --version ${WIX_VERSION}
wix.exe extension add WixToolset.UI.wixext/6.0.0 --global wix.exe extension add --global WixToolset.UI.wixext/${WIX_VERSION}
wix.exe extension add WixToolset.Util.wixext/6.0.0 --global wix.exe extension add --global WixToolset.Util.wixext/${WIX_VERSION}
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
@@ -140,8 +143,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\""
@@ -200,7 +203,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@1074588008ae3326a2221ea451783280518f0366 # no specific version uses: skymatic/workflows/.github/actions/win-sign-action@957d3c2c08c56855fdac41e5afb9a7aca8c30dd9 # no specific version
with: with:
base-dir: 'appdir' base-dir: 'appdir'
file-extensions: 'dll,exe,ps1' file-extensions: 'dll,exe,ps1'
@@ -246,9 +249,11 @@ 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
@@ -275,7 +280,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@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with: with:
name: msi-${{ matrix.arch }} name: msi-${{ matrix.arch }}
path: | path: |
@@ -297,21 +302,23 @@ jobs:
java-version: '24.0.1+9' java-version: '24.0.1+9'
java-package: 'jdk' java-package: 'jdk'
steps: steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Install wix and extensions - name: Install wix and extensions
run: | run: |
dotnet tool install --global wix --version 6.0.0 dotnet tool install --global wix --version ${WIX_VERSION}
wix.exe extension add WixToolset.BootstrapperApplications.wixext/6.0.0 --global wix.exe extension add --global WixToolset.BootstrapperApplications.wixext/${WIX_VERSION}
wix.exe extension add WixToolset.Util.wixext/6.0.0 --global wix.exe extension add --global WixToolset.Util.wixext/${WIX_VERSION}
env:
WIX_VERSION: ${{ env.WIX_VERSION }}
- name: Download .msi - name: Download .msi
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.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@f2beeb24e141e01a676f977032f5a29d81c9e27e # v5.1.0 uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with: with:
distribution: ${{ matrix.java-dist }} distribution: ${{ matrix.java-dist }}
java-version: ${{ matrix.java-version }} java-version: ${{ matrix.java-version }}
@@ -374,7 +381,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@1074588008ae3326a2221ea451783280518f0366 # no specific version uses: skymatic/workflows/.github/actions/win-sign-action@957d3c2c08c56855fdac41e5afb9a7aca8c30dd9 # no specific version
with: with:
base-dir: 'tmp' base-dir: 'tmp'
file-extensions: 'exe' file-extensions: 'exe'
@@ -398,7 +405,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@1074588008ae3326a2221ea451783280518f0366 # no specific version uses: skymatic/workflows/.github/actions/win-sign-action@957d3c2c08c56855fdac41e5afb9a7aca8c30dd9 # no specific version
with: with:
base-dir: 'installer' base-dir: 'installer'
file-extensions: 'exe' file-extensions: 'exe'
@@ -416,7 +423,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@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with: with:
name: exe-${{ matrix.executable-suffix }} name: exe-${{ matrix.executable-suffix }}
path: | path: |
@@ -434,7 +441,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@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with: with:
merge-multiple: true merge-multiple: true
- name: Publish installers on GitHub Releases - name: Publish installers on GitHub Releases
+33 -10
View File
@@ -12,17 +12,15 @@
<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.57.2/dagger-compiler-2.57.2.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.57.2/dagger-2.57.2.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$/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.57.2/dagger-spi-2.57.2.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/code/findbugs/jsr305/3.0.2/jsr305-3.0.2.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/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.5/google-java-format-1.5.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/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" />
@@ -37,8 +35,33 @@
<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.1.21/kotlin-metadata-jvm-2.1.21.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.1.21/kotlin-stdlib-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/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" />
@@ -47,7 +70,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 -Adagger.formatGeneratedSource=enabled" /> <module name="cryptomator" options="-Adagger.fastInit=enabled" />
</option> </option>
</component> </component>
</project> </project>
+34 -8
View File
@@ -10,15 +10,41 @@ Changes to prior versions can be found on the [Github release page](https://gith
## [Unreleased](https://github.com/cryptomator/cryptomator/compare/1.18.0...HEAD) ## [Unreleased](https://github.com/cryptomator/cryptomator/compare/1.18.0...HEAD)
### Added ### Added
* Self-Update Mechanism (#3948) * Self-Update Mechanism ([#3948](https://github.com/cryptomator/cryptomator/pull/3948))
* Implemented `.dmg` update mechanism * Implemented `.dmg` update mechanism
* Implemented Flatpak update mechanism * Implemented Flatpak update mechanism
* App notifications (#4069) * App notifications ([#4069](https://github.com/cryptomator/cryptomator/pull/4069))
* Mark files in-use for Hub vaults (#4078) * Mark files in-use for Hub vaults ([#4078](https://github.com/cryptomator/cryptomator/pull/4078))
* Accessibility: Adjust app to be used with a screen reader ([#547](https://github.com/cryptomator/cryptomator/issues/547))
### Changed * Show Archived Vault Dialog on unlock when Hub returns 410 ([#4081](https://github.com/cryptomator/cryptomator/pull/4081))
* Built using JDK 25 (#4031) * Support automatic app theme selection according to OS theme on Linux ([#4027](https://github.com/cryptomator/cryptomator/issues/4027))
* Modernized Templage for GitHub Releases * 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))
### Fixed ### Fixed
* Windows: Removed debug launcher start menu entry ([#4089](https://github.com/cryptomator/cryptomator/issues/4089)) * 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))
### Changed
* Disable user defined app start config on Windows ([#4132](https://github.com/cryptomator/cryptomator/issues/4132))
* Disable plugin loading by default ([#4136](https://github.com/cryptomator/cryptomator/4136))
* 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.31
* `com.fasterxml.jackson.core:jackson-databind` from 2.20.0 to 2.21.0
* `com.fasterxml.jackson.datatype:jackson-datatype-jsr310` from 2.20.0 to 2.21.0
* `com.github.ben-manes.caffeine:caffeine` from 3.2.2 to 3.2.3
* `com.google.dagger:*` from 2.57.2 to 2.59.1
* `org.apache.commons:commons-lang3` from 3.19.0 to 3.20.0
* `org.cryptomator:cryptofs` from 2.9.0 to 2.10.0-beta3
* `org.cryptomator:cryptolib` from 2.2.1 to 2.2.2
* `org.cryptomator:fuse-nio-adapter` from 5.1.0 to 6.0.0
* `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
+1 -1
View File
@@ -78,7 +78,7 @@ For more information on the security details visit [cryptomator.org](https://doc
### Dependencies ### Dependencies
* JDK 24 (e.g. temurin, zulu) * JDK 25 (e.g. temurin, zulu)
* Maven 3 * Maven 3
### Run Maven ### Run Maven
+8
View File
@@ -0,0 +1,8 @@
# 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
+4 -4
View File
@@ -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 JAVAFX_VERSION=25.0.2
JAVAFX_ARCH="x64" JAVAFX_ARCH="x64"
JAVAFX_JMODS_SHA256='96e520f48610d8ffb94ca30face1f11ffe8a977ddc1c4ff80b1a9e9f048bd94e' JAVAFX_JMODS_SHA256='e0a9c29d8cf3af9b8b48848b43f87b5785bc107c53a951b19668ce05842bba1b'
if [ "${CPU_ARCH}" = "aarch64" ]; then if [ "${CPU_ARCH}" = "aarch64" ]; then
JAVAFX_ARCH="aarch64" JAVAFX_ARCH="aarch64"
JAVAFX_JMODS_SHA256='951c52481af0ec5885b06f1ebaa8a10da7e8ea23c5e1ef3e2f6f11fa1b3a7ce1' JAVAFX_JMODS_SHA256='c3408f818693cce09e59829a8e862a82c7695fdfcd585c41cfd527f5fc3fe646'
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\"" \
+1 -1
View File
@@ -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\"" \
+4 -4
View File
@@ -32,15 +32,15 @@ REVISION_NO=`git rev-list --count HEAD`
VERSION_NO=`mvn -f../../../pom.xml help:evaluate -Dexpression=project.version -q -DforceStdout | sed -rn 's/.*([0-9]+\.[0-9]+\.[0-9]+).*/\1/p'` VERSION_NO=`mvn -f../../../pom.xml help:evaluate -Dexpression=project.version -q -DforceStdout | sed -rn 's/.*([0-9]+\.[0-9]+\.[0-9]+).*/\1/p'`
FUSE_LIB="FUSE-T" FUSE_LIB="FUSE-T"
JAVAFX_VERSION=25 JAVAFX_VERSION=25.0.2
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="13f8c0513c40c95881479fbcf0465a29a60217393fb0656f5e4eab78a9442fba" JAVAFX_JMODS_SHA256="4cd258001c75af7047005c5c891e2400ed11d24fbb09412324c0cbaf8b503c5a"
else else
JAVAFX_ARCH="x64" JAVAFX_ARCH="x64"
JAVAFX_JMODS_SHA256="0eba73fb28a24c845175d16fa2f8c081c936ce6de1be9b79eb6119fa32e53d52" JAVAFX_JMODS_SHA256="0b4d8463f03901b7425d94628e4116b7078abb8dd540fbec415266fac20bda5c"
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\"" \
+9 -7
View File
@@ -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.0)' Write-Error 'Unable to find wix in your PATH (try: dotnet tool install --global wix --version 6.0.2)'
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.0 --global)' Write-Error 'Wix UI extension missing. Please install it with: wix.exe extension add WixToolset.UI.wixext/6.0.2 --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.0 --global)' Write-Error 'Wix Util extension missing. Please install it with: wix.exe extension add WixToolset.Util.wixext/6.0.2 --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.0 --global)' Write-Error 'Wix Bootstrapper extension missing. Please install it with: wix.exe extension add WixToolset.BootstrapperApplications.wixext/6.0.2 --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' $javaFxVersion='25.0.2'
$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 = 'c8eb9fd039b00e0020cf6c3db8ed7876bf3ee4d27860aa697a247b83b8296ae7' $javaFxJmodsSHA256 = '33d878dfac85590c4d77c518ed413e512d34a8479d90132b230a7ddd173576b3'
$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.pluginDir=`"@{appdata}/$AppName/Plugins`"" "--java-options", "-Dcryptomator.adminConfigPath=`"C:/ProgramData/$AppName/config.properties`""
"--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,8 +221,10 @@ $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
View File
@@ -0,0 +1,12 @@
@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
View File
@@ -0,0 +1,24 @@
# 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
}
+84 -66
View File
@@ -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,21 +13,20 @@
<?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 ?>
@@ -43,7 +42,8 @@
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)"/> IncludeMaximum="$(var.JpUpgradeVersionOnlyDetectUpgrade)"/> <!-- TODO in earlier versions, this was set to yes-->
<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?>
<!-- in order to sign the DLL, the path to the dll can be specified --> <!-- TODO: how does this work again? -->
<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,24 +99,35 @@
</ns0:Component> </ns0:Component>
</ns0:DirectoryRef> </ns0:DirectoryRef>
<ns0:DirectoryRef Id="ProgramMenuFolder"> <ns0:StandardDirectory Id="CommonAppDataFolder">
<!-- Shortcut with set AUMID --> <ns0:Directory Id="CryptomatorDesktopProgramData" Name="Cryptomator">
<ns0:Component Guid="{88290d4b-0b71-4568-a4b6-70d6b0498c9c}" Bitness="always64" Id="CustomShortcuts"> <ns0:Component Id="AdminConfigDir" Guid="c078b7da-ba6e-4069-a5ab-5c0f0f9856a0">
<ns0:RegistryKey Root="HKLM" Key="Software\$(var.JpAppVendor)\$(var.JpAppName)\$(var.JpAppVersion)"> <ns0:CreateFolder>
<ns0:RegistryValue Type="string" KeyPath="yes" Name="ProductCode" Value="[ProductCode]"/> <util:PermissionEx User="SYSTEM" GenericAll="yes"/>
</ns0:RegistryKey> <util:PermissionEx User="Administrators" GenericAll="yes"/>
<ns0:Shortcut Id="appShortcut" Name="$(var.JpAppName)" Advertise="no" Target="[INSTALLDIR]$(var.JpAppName).exe"> <util:PermissionEx User="Users" GenericRead="yes" GenericExecute="yes"/>
<ns0:ShortcutProperty Key="System.AppUserModel.ID" Value="$(var.AppUserModelId)"/> </ns0:CreateFolder>
</ns0:Shortcut>
</ns0:Component> </ns0:Component>
</ns0:DirectoryRef> <ns0:Component Id="AdminConfigFile" NeverOverwrite="yes" Permanent="yes">
<ns0:File Id="EmptyAdminConfig" Source="$(env.JP_WIXWIZARD_RESOURCES)\..\..\common\cryptomator.config" Name="cryptomator.config" 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"/>
<ns0:ComponentRef Id="NonStartingProgID" /> <!-- Ref to additional ProgIDs -->
<ns0:ComponentRef Id="CustomShortcuts" /> <ns0:ComponentRef Id="nonStartingProgID"/>
<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]" />
@@ -125,31 +136,33 @@
<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="&quot;[INSTALLDIR]disableUserConfig.bat&quot;" 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="&quot;[INSTALLDIR]patchWebDAV.bat&quot; &quot;$(var.LoopbackAlias)&quot;" Sequence="execute" Before="PatchWebDAV"/> <ns0:SetProperty Id="PatchWebDAV" Value="&quot;[INSTALLDIR]patchWebDAV.bat&quot; &quot;$(var.LoopbackAlias)&quot;" 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="&quot;[INSTALLDIR]patchUpdateCheck.bat&quot; &quot;[DISABLEUPDATECHECK]&quot;" Sequence="execute" Before="PatchUpdateCheck"/> <ns0:SetProperty Id="PatchUpdateCheck" Value="&quot;[INSTALLDIR]patchUpdateCheck.bat&quot; &quot;[DISABLEUPDATECHECK]&quot;" 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 -->
@@ -165,40 +178,45 @@
/> />
<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="InstallFiles" Condition="NOT (Installed AND (NOT REINSTALL) AND (NOT UPGRADINGPRODUCTCODE) AND REMOVE)"/> <ns0:Custom Action="PatchWebDAV" After="DisableUserConfig" 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>
@@ -207,7 +225,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>
+6 -5
View File
@@ -18,16 +18,17 @@ 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.
By default it is defined for applications and undefined for Runtime installer. Default value is `yes`.
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.
By default it is defined, use <?undef JpAllowUpgrades?> to disable. --> Default value is `yes`.
-->
<!-- Cryptomator Section <!-- Cryptomator Section
+16 -15
View File
@@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>org.cryptomator</groupId> <groupId>org.cryptomator</groupId>
<artifactId>cryptomator</artifactId> <artifactId>cryptomator</artifactId>
<version>1.19.0-SNAPSHOT</version> <version>1.19.0</version>
<name>Cryptomator Desktop App</name> <name>Cryptomator Desktop App</name>
<organization> <organization>
@@ -33,23 +33,25 @@
<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-beta2</cryptomator.cryptofs.version> <cryptomator.cryptofs.version>2.10.0-beta3</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.5.1</cryptomator.integrations.win.version> <cryptomator.integrations.win.version>1.6.0</cryptomator.integrations.win.version>
<cryptomator.integrations.mac.version>1.5.0-beta1</cryptomator.integrations.mac.version> <cryptomator.integrations.mac.version>1.5.0-beta3</cryptomator.integrations.mac.version>
<cryptomator.integrations.linux.version>1.7.0-beta1</cryptomator.integrations.linux.version> <cryptomator.integrations.linux.version>1.7.0-beta4</cryptomator.integrations.linux.version>
<cryptomator.fuse.version>5.1.0</cryptomator.fuse.version> <cryptomator.fuse.version>6.0.0</cryptomator.fuse.version>
<cryptomator.webdav.version>3.0.0</cryptomator.webdav.version> <cryptomator.webdav.version>3.0.1</cryptomator.webdav.version>
<!-- 3rd party dependencies --> <!-- 3rd party dependencies -->
<commons-lang3.version>3.19.0</commons-lang3.version> <caffeine.version>3.2.3</caffeine.version>
<dagger.version>2.57.2</dagger.version> <commons-lang3.version>3.20.0</commons-lang3.version>
<dagger.version>2.59.1</dagger.version>
<easybind.version>2.2</easybind.version> <easybind.version>2.2</easybind.version>
<jackson.version>2.20.0</jackson.version> <jackson.version>2.21.0</jackson.version>
<javafx.version>25</javafx.version> <javafx.version>25.0.2</javafx.version>
<jwt.version>4.5.0</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.19</logback.version> <logback.version>1.5.31</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>
@@ -94,7 +96,7 @@
<dependency> <dependency>
<groupId>org.cryptomator</groupId> <groupId>org.cryptomator</groupId>
<artifactId>cryptolib</artifactId> <artifactId>cryptolib</artifactId>
<version>2.2.1</version> <version>${cryptomator.cryptolib.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.cryptomator</groupId> <groupId>org.cryptomator</groupId>
@@ -228,7 +230,7 @@
<dependency> <dependency>
<groupId>com.github.ben-manes.caffeine</groupId> <groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId> <artifactId>caffeine</artifactId>
<version>3.2.2</version> <version>${caffeine.version}</version>
</dependency> </dependency>
<!-- JUnit / Mockito / Hamcrest --> <!-- JUnit / Mockito / Hamcrest -->
<dependency> <dependency>
@@ -330,7 +332,6 @@
</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>
+3
View File
@@ -14,11 +14,13 @@ 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.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.JfxUiAppearanceProvider;
import org.cryptomator.ui.traymenu.AwtTrayMenuController; import org.cryptomator.ui.traymenu.AwtTrayMenuController;
open module org.cryptomator.desktop { open module org.cryptomator.desktop {
@@ -61,6 +63,7 @@ open module org.cryptomator.desktop {
uses SSLContextProvider; uses SSLContextProvider;
uses org.cryptomator.event.NotificationHandler; uses org.cryptomator.event.NotificationHandler;
provides UiAppearanceProvider with JfxUiAppearanceProvider;
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;
@@ -61,6 +61,7 @@ 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,11 +153,6 @@ 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,14 +10,6 @@ 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) {
@@ -0,0 +1,97 @@
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,7 +35,8 @@ public class Cryptomator {
private static final long STARTUP_TIME = System.currentTimeMillis(); private static final long STARTUP_TIME = System.currentTimeMillis();
static { static {
var lazyProcessedProps = new SubstitutingProperties(System.getProperties(), System.getenv()); var adminProps = AdminPropertiesFactory.create();
var lazyProcessedProps = new SubstitutingProperties(adminProps, System.getenv());
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);
@@ -64,6 +65,7 @@ public class Cryptomator {
} }
public static void main(String[] args) { public static void main(String[] args) {
EventualLogger.INSTANCE.drainTo(LOG);
var printVersion = Optional.ofNullable(args) // var printVersion = Optional.ofNullable(args) //
.stream() //Streams either one element (the args-array) or zero elements .stream() //Streams either one element (the args-array) or zero elements
.flatMap(Arrays::stream) // .flatMap(Arrays::stream) //
@@ -4,7 +4,6 @@ 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;
@@ -30,11 +29,6 @@ class CryptomatorModule {
return new ArrayBlockingQueue<>(10); return new ArrayBlockingQueue<>(10);
} }
@Provides
@Singleton
static Optional<UiAppearanceProvider> provideAppearanceProvider() {
return UiAppearanceProvider.get();
}
@Provides @Provides
@Singleton @Singleton
@@ -0,0 +1,106 @@
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;
}
}
@@ -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.appliedThemeProperty().map(this::selectScreenshot); this.screenshot = applicationStyle.appliedAppThemeProperty().map(this::selectScreenshot);
} }
private Image selectScreenshot(Theme theme) { private Image selectScreenshot(Theme theme) {
@@ -4,24 +4,27 @@ 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 NotificationBar extends HBox { public class InfoBar extends HBox {
@FXML @FXML
private Label notificationLabel; private Label infoMessage;
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 NotificationBar() { public InfoBar() {
setAlignment(Pos.CENTER); setAlignment(Pos.CENTER);
setStyle("-fx-alignment: center;"); getStyleClass().addAll("info-bar");
Region spacer = new Region(); Region spacer = new Region();
spacer.setMinWidth(40); spacer.setMinWidth(40);
@@ -36,14 +39,21 @@ public class NotificationBar 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);
notificationLabel = new Label(); infoMessage = new Label();
notificationLabel.getStyleClass().add("notification-label"); infoMessage.setFocusTraversable(true);
notificationLabel.setStyle("-fx-alignment: center;"); infoMessage.setAccessibleRole(AccessibleRole.BUTTON);
vbox.getChildren().add(notificationLabel); vbox.getChildren().add(infoMessage);
Button closeButton = new Button("X"); var closeGraphic = new FontAwesome5IconView();
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(_ -> {
@@ -61,11 +71,11 @@ public class NotificationBar extends HBox {
} }
public String getText() { public String getText() {
return notificationLabel.getText(); return infoMessage.getText();
} }
public void setText(String text) { public void setText(String text) {
notificationLabel.setText(text); infoMessage.setText(text);
} }
public void setStyleClass(String styleClass) { public void setStyleClass(String styleClass) {
@@ -61,6 +61,15 @@ 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") //
@@ -7,6 +7,7 @@ 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;
@@ -26,6 +27,7 @@ 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, //
@@ -41,7 +43,7 @@ import java.io.InputStream;
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 {
@@ -50,6 +52,12 @@ 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,82 +36,91 @@ 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, @SuppressWarnings("unused") UiTheme oldValue, UiTheme newValue) { private void appThemeChanged(@SuppressWarnings("unused") ObservableValue<? extends UiTheme> observable, UiTheme oldValue, UiTheme newValue) {
if (appearanceProvider.isPresent() && oldValue == UiTheme.AUTOMATIC && newValue != UiTheme.AUTOMATIC) { if (oldValue == newValue) {
// 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.error("Failed to disable automatic theme switching."); LOG.warn("Failed to disable automatic theme switching.", e);
}
}
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 systemInterfaceThemeChanged(Theme theme) { private void registerOsThemeListener() {
switch (theme) {
case LIGHT -> applyLightTheme();
case DARK -> applyDarkTheme();
}
}
private void applySystemTheme() {
if (appearanceProvider.isPresent()) { if (appearanceProvider.isPresent()) {
systemInterfaceThemeChanged(appearanceProvider.get().getSystemTheme()); try {
appearanceProvider.get().addListener(systemInterfaceThemeListener);
} catch (UiAppearanceException e) {
LOG.warn("Failed to enable automatic theme switching.", e);
}
} else { } else {
LOG.warn("No UiAppearanceProvider present, assuming LIGHT theme..."); LOG.warn("Unable to register for os theme changes: No supported UiAppearanceProvider present");
applyLightTheme();
} }
} }
private void applyLightTheme() { private void applyTheme(UiTheme uiTheme) {
var stylesheet = Optional // if (!licenseHolder.isValidLicense()) {
.ofNullable(getClass().getResource("/css/light_theme.bss")) // loadAndApplyLightTheme();
.orElse(getClass().getResource("/css/light_theme.css")); } else {
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) {
LOG.warn("Failed to load light_theme stylesheet"); throw new IllegalStateException("Cannot find resource %s".formatted(cssFile));
} 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);
} }
private void applyDarkTheme() { public ObjectProperty<Theme> appliedAppThemeProperty() {
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,6 +3,8 @@ 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;
@@ -11,6 +13,7 @@ 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;
@@ -23,6 +26,8 @@ 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;
@@ -37,7 +42,13 @@ public class FxFSEventList {
} }
public void schedulePollForUpdates() { public void schedulePollForUpdates() {
scheduler.schedule(this::checkForEventUpdates, 1000, TimeUnit.MILLISECONDS); try {
scheduler.schedule(this::checkForEventUpdates, 1000, TimeUnit.MILLISECONDS);
} catch ( RejectedExecutionException e) {
if(!scheduler.isShutdown()) {
LOG.warn("Failed to poll for filesystem events", e);
}
}
} }
/** /**
@@ -0,0 +1,68 @@
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));
}
}
}
@@ -11,6 +11,7 @@ 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;
@@ -58,6 +59,8 @@ 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, //
@@ -72,7 +75,8 @@ 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)
@@ -87,6 +91,8 @@ 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
@@ -226,7 +232,8 @@ 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, 410 -> accessNotGranted(); // or vault has been archived, effectively disallowing access - TODO: add specific dialog? case 403 -> accessNotGranted();
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());
} }
@@ -270,7 +277,8 @@ 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, 410 -> accessNotGranted(); // or vault has been archived, effectively disallowing access case 403 -> accessNotGranted();
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());
} }
@@ -303,6 +311,11 @@ 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());
} }
@@ -16,6 +16,7 @@ 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 {
@@ -23,9 +24,12 @@ 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;
@@ -35,17 +39,21 @@ public class VaultListCellController implements FxController {
public HBox vaultListCell; public HBox vaultListCell;
@Inject @Inject
VaultListCellController(Settings settings) { VaultListCellController(Settings settings, ResourceBundle resourceBundle) {
this.glyph = vault.flatMap(Vault::stateProperty).map(this::getGlyphForVaultState); this.resourceBundle = resourceBundle;
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(vault.flatMap(Vault::stateProperty).map(VaultState.Value.PROCESSING::equals).orElse(false)) // .onCondition(vaultState.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
@@ -62,6 +70,25 @@ 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,15 +101,10 @@ 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("File is locked by another device");
fileName.set(cleartextFileName);
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")); message.set(resourceBundle.getString("notification.inUse.message"));
description.set(resourceBundle.getString("notification.inUse.description").formatted(fiiue.cleartextPath(), user, device)); fileName.set(cleartextFileName);
description.set(resourceBundle.getString("notification.inUse.description").formatted(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");
@@ -101,8 +101,9 @@ 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 only migrate on macOS (touchID vs regular keychain) //currently, we migrate on macOS (touchID vs regular keychain)
if (SystemUtils.IS_OS_MAC) { //and on Linux (GNOME Keyring / KDE Wallet / Secret Service)
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()) {
@@ -56,7 +56,7 @@ public class InterfacePreferencesController implements FxController {
@FXML @FXML
public void initialize() { public void initialize() {
themeChoiceBox.getItems().addAll(UiTheme.applicableValues()); themeChoiceBox.getItems().addAll(UiTheme.values());
if (!themeChoiceBox.getItems().contains(settings.theme.get())) { if (!themeChoiceBox.getItems().contains(settings.theme.get())) {
settings.theme.set(UiTheme.LIGHT); settings.theme.set(UiTheme.LIGHT);
} }
@@ -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((_) -> restoreWithPassword()); nextButton.setOnAction((_) -> restoreWithPasswordAsync());
} }
} }
@@ -137,11 +137,47 @@ public class RecoveryKeyCreationController implements FxController {
} }
@FXML @FXML
public void restoreWithPassword() { public void restoreWithPasswordAsync() {
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())) {
@@ -152,23 +188,6 @@ 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);
} }
} }
@@ -117,14 +117,46 @@ public class RecoveryKeyResetPasswordController implements FxController {
@FXML @FXML
public void next() { public void next() {
switch (recoverType.get()) { switch (recoverType.get()) {
case RESTORE_ALL -> restorePassword(); case RESTORE_ALL -> restorePasswordAsync();
case RESTORE_MASTERKEY, RESET_PASSWORD -> resetPassword(); case RESTORE_MASTERKEY, RESET_PASSWORD -> resetPassword();
default -> resetPassword(); // Fallback default -> resetPassword(); // Fallback
} }
} }
@FXML @FXML
public void restorePassword() { public void restorePasswordAsync() {
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());
@@ -135,19 +167,6 @@ 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);
} }
} }
@@ -0,0 +1,25 @@
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,11 +9,15 @@ 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 {
@@ -25,6 +29,7 @@ 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
@@ -40,6 +45,7 @@ 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
@@ -70,4 +76,12 @@ 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();
}
} }
+45 -19
View File
@@ -50,6 +50,7 @@
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;
@@ -387,37 +388,62 @@
/******************************************************************************* /*******************************************************************************
* * * *
* NotificationBar * * InfoBar *
* * * *
******************************************************************************/ ******************************************************************************/
.info-bar {
-fx-alignment: center;
-fx-min-height:24px;
-fx-max-height:24px;
-fx-background-color: -bar-bg;
}
.notification-label { .info-bar--green {
-fx-text-fill: white; -bar-bg: GREEN_5;
-button-bg: GREEN_5;
-button-bg-pressed: GREEN_3;
}
.info-bar--yellow {
-bar-bg: YELLOW_5;
-button-bg: YELLOW_5;
-button-bg-pressed: YELLOW_4;
}
.info-bar--red {
-bar-bg: RED_5;
-button-bg: RED_5;
-button-bg-pressed: RED_5;
}
.info-bar .label {
-fx-text-fill: GRAY_9;
-fx-font-weight: bold; -fx-font-weight: bold;
} }
.notification-debug { .info-bar--yellow .label {
-fx-min-height:24px; -fx-text-fill: GRAY_9;
-fx-max-height:24px; -fx-font-weight: bold;
-fx-background-color: RED_5; -fx-effect: dropshadow( gaussian , rgba(0,0,0,0.45) , 2 , 0 , 0 , 1 );
} }
.notification-update { .info-bar .glyph {
-fx-min-height:24px; -fx-fill: GRAY_9;
-fx-max-height:24px;
-fx-background-color: YELLOW_5;
} }
.notification-support { .info-bar:hover .label {
-fx-min-height:24px; -fx-underline:true;
-fx-max-height:24px;
-fx-background-color: PRIMARY;
} }
.notification-debug:hover .notification-label, .info-bar .button {
.notification-update:hover .notification-label, -fx-background-color: transparent;
.notification-support:hover .notification-label { -fx-border-color: transparent;
-fx-underline:true; -fx-padding: 2 2 2 2;
}
.info-bar .button:armed {
-fx-background-color: -button-bg-pressed;
-fx-background-radius: 8;
} }
/******************************************************************************* /*******************************************************************************
+46 -20
View File
@@ -50,6 +50,7 @@
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;
@@ -387,39 +388,64 @@
/******************************************************************************* /*******************************************************************************
* * * *
* NotificationBar * * InfoBar *
* * * *
******************************************************************************/ ******************************************************************************/
.info-bar {
-fx-alignment: center;
-fx-min-height:24px;
-fx-max-height:24px;
-fx-background-color: -bar-bg;
}
.notification-label { .info-bar--green {
-fx-text-fill: white; -bar-bg: GREEN_5;
-button-bg: GREEN_5;
-button-bg-pressed: GREEN_3;
}
.info-bar--yellow {
-bar-bg: YELLOW_5;
-button-bg: YELLOW_5;
-button-bg-pressed: YELLOW_4;
}
.info-bar--red {
-bar-bg: RED_5;
-button-bg: RED_5;
-button-bg-pressed: RED_5;
}
.info-bar .label {
-fx-text-fill: GRAY_9;
-fx-font-weight: bold; -fx-font-weight: bold;
} }
.notification-debug { .info-bar--yellow .label {
-fx-min-height:24px; -fx-text-fill: GRAY_9;
-fx-max-height:24px; -fx-font-weight: bold;
-fx-background-color: RED_5; -fx-effect: dropshadow( gaussian , rgba(0,0,0,0.45) , 2 , 0 , 0 , 1 );
} }
.notification-update { .info-bar .glyph {
-fx-min-height:24px; -fx-fill: GRAY_9;
-fx-max-height:24px;
-fx-background-color: YELLOW_5;
} }
.notification-support { .info-bar:hover .label {
-fx-min-height:24px;
-fx-max-height:24px;
-fx-background-color: PRIMARY;
}
.notification-debug:hover .notification-label,
.notification-update:hover .notification-label,
.notification-support:hover .notification-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,7 +13,8 @@
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,7 +19,8 @@
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,7 +19,8 @@
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,7 +17,8 @@
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,7 +15,8 @@
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,7 +11,8 @@
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,7 +16,8 @@
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>
+2 -1
View File
@@ -13,7 +13,8 @@
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,7 +18,8 @@
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,7 +15,8 @@
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,7 +19,8 @@
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>
+2 -1
View File
@@ -22,7 +22,8 @@
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>
+2 -1
View File
@@ -21,7 +21,8 @@
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,7 +18,8 @@
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,7 +20,8 @@
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,7 +18,8 @@
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>
+2 -1
View File
@@ -20,7 +20,8 @@
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>
+2 -1
View File
@@ -18,7 +18,8 @@
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,7 +20,8 @@
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>
@@ -11,6 +11,7 @@
<?import javafx.scene.layout.StackPane?> <?import javafx.scene.layout.StackPane?>
<?import javafx.scene.layout.VBox?> <?import javafx.scene.layout.VBox?>
<?import javafx.scene.shape.Circle?> <?import javafx.scene.shape.Circle?>
<!-- TODO: simple dialog -->
<HBox xmlns:fx="http://javafx.com/fxml" <HBox xmlns:fx="http://javafx.com/fxml"
xmlns="http://javafx.com/javafx" xmlns="http://javafx.com/javafx"
fx:controller="org.cryptomator.ui.keyloading.hub.RegisterFailedController" fx:controller="org.cryptomator.ui.keyloading.hub.RegisterFailedController"
@@ -18,7 +19,8 @@
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,7 +18,8 @@
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,7 +18,8 @@
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>
@@ -21,7 +21,8 @@
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,7 +18,8 @@
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>
+2 -1
View File
@@ -19,7 +19,8 @@
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>
+2 -1
View File
@@ -19,7 +19,8 @@
maxWidth="500" maxWidth="500"
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>
+7 -7
View File
@@ -3,7 +3,7 @@
<?import javafx.scene.control.SplitPane?> <?import javafx.scene.control.SplitPane?>
<?import javafx.scene.layout.StackPane?> <?import javafx.scene.layout.StackPane?>
<?import javafx.scene.layout.VBox?> <?import javafx.scene.layout.VBox?>
<?import org.cryptomator.ui.controls.NotificationBar?> <?import org.cryptomator.ui.controls.InfoBar?>
<StackPane xmlns:fx="http://javafx.com/fxml" <StackPane xmlns:fx="http://javafx.com/fxml"
xmlns="http://javafx.com/javafx" xmlns="http://javafx.com/javafx"
@@ -11,23 +11,23 @@
fx:controller="org.cryptomator.ui.mainwindow.MainWindowController" fx:controller="org.cryptomator.ui.mainwindow.MainWindowController"
styleClass="main-window"> styleClass="main-window">
<VBox minWidth="600"> <VBox minWidth="600">
<NotificationBar onMouseClicked="#showUpdatePreferences" <InfoBar onMouseClicked="#showUpdatePreferences"
text="%main.notification.updateAvailable" text="%main.notification.updateAvailable"
dismissable="true" dismissable="true"
notify="${controller.updateAvailable}" notify="${controller.updateAvailable}"
styleClass="notification-update"/> styleClass="info-bar--yellow"/>
<NotificationBar onMouseClicked="#showContributePreferences" <InfoBar onMouseClicked="#showContributePreferences"
text="%main.notification.support" text="%main.notification.support"
dismissable="true" dismissable="true"
notify="${!controller.licenseValid}" notify="${!controller.licenseValid}"
styleClass="notification-support"/> styleClass="info-bar--green"/>
<SplitPane dividerPositions="0.33" orientation="HORIZONTAL" VBox.vgrow="ALWAYS"> <SplitPane dividerPositions="0.33" orientation="HORIZONTAL" VBox.vgrow="ALWAYS">
<fx:include source="vault_list.fxml" SplitPane.resizableWithParent="false"/> <fx:include source="vault_list.fxml" SplitPane.resizableWithParent="false"/>
<fx:include source="vault_detail.fxml" SplitPane.resizableWithParent="true"/> <fx:include source="vault_detail.fxml" SplitPane.resizableWithParent="true"/>
</SplitPane> </SplitPane>
<NotificationBar onMouseClicked="#showGeneralPreferences" <InfoBar onMouseClicked="#showGeneralPreferences"
text="DEBUG MODE" text="DEBUG MODE"
styleClass="notification-debug" styleClass="info-bar--red"
notify="${controller.debugModeEnabled}"/> notify="${controller.debugModeEnabled}"/>
</VBox> </VBox>
</StackPane> </StackPane>
@@ -16,7 +16,8 @@
minWidth="400" minWidth="400"
maxWidth="400" maxWidth="400"
minHeight="145" minHeight="145"
spacing="12"> spacing="12"
accessibleRole="DIALOG">
<padding> <padding>
<Insets topRightBottomLeft="12"/> <Insets topRightBottomLeft="12"/>
</padding> </padding>
@@ -19,7 +19,8 @@
minWidth="400" minWidth="400"
maxWidth="400" maxWidth="400"
minHeight="145" minHeight="145"
spacing="12"> spacing="12"
accessibleRole="DIALOG">
<padding> <padding>
<Insets topRightBottomLeft="12"/> <Insets topRightBottomLeft="12"/>
</padding> </padding>
+2 -1
View File
@@ -20,7 +20,8 @@
fx:controller="org.cryptomator.ui.migration.MigrationStartController" fx:controller="org.cryptomator.ui.migration.MigrationStartController"
prefWidth="580" prefWidth="580"
prefHeight="350" prefHeight="350"
spacing="12"> spacing="12"
accessibleRole="DIALOG">
<padding> <padding>
<Insets topRightBottomLeft="12"/> <Insets topRightBottomLeft="12"/>
</padding> </padding>
@@ -15,7 +15,8 @@
minWidth="400" minWidth="400"
maxWidth="400" maxWidth="400"
minHeight="145" minHeight="145"
spacing="12"> spacing="12"
accessibleRole="DIALOG">
<padding> <padding>
<Insets topRightBottomLeft="12"/> <Insets topRightBottomLeft="12"/>
</padding> </padding>
+2 -1
View File
@@ -16,7 +16,8 @@
xmlns:fx="http://javafx.com/fxml" xmlns:fx="http://javafx.com/fxml"
fx:controller="org.cryptomator.ui.notification.NotificationController" fx:controller="org.cryptomator.ui.notification.NotificationController"
prefHeight="200.0" prefWidth="400.0" maxHeight="200.0" maxWidth="400.0" prefHeight="200.0" prefWidth="400.0" maxHeight="200.0" maxWidth="400.0"
styleClass="notification-window"> styleClass="notification-window"
accessibleRole="DIALOG">
<padding> <padding>
<Insets top="12" right="12" bottom="12" left="12"/> <Insets top="12" right="12" bottom="12" left="12"/>
</padding> </padding>
+2 -1
View File
@@ -19,7 +19,8 @@
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>
+2 -1
View File
@@ -19,7 +19,8 @@
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,7 +20,8 @@
maxWidth="400" maxWidth="400"
minHeight="175" minHeight="175"
spacing="12" spacing="12"
alignment="TOP_LEFT"> alignment="TOP_LEFT"
accessibleRole="DIALOG">
<padding> <padding>
<Insets topRightBottomLeft="12"/> <Insets topRightBottomLeft="12"/>
</padding> </padding>
@@ -14,7 +14,8 @@
minWidth="350" minWidth="350"
minHeight="280" minHeight="280"
spacing="12" spacing="12"
alignment="TOP_LEFT"> alignment="TOP_LEFT"
accessibleRole="DIALOG">
<children> <children>
<FormattedLabel format="%recoveryKey.display.description" arg1="${controller.vaultName}" wrapText="true" labelFor="$textarea"/> <FormattedLabel format="%recoveryKey.display.description" arg1="${controller.vaultName}" wrapText="true" labelFor="$textarea"/>
@@ -22,7 +22,8 @@
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>
@@ -25,7 +25,8 @@
prefWidth="480" prefWidth="480"
minHeight="242" minHeight="242"
spacing="12" spacing="12"
VBox.vgrow="ALWAYS"> VBox.vgrow="ALWAYS"
accessibleRole="DIALOG">
<padding> <padding>
<Insets topRightBottomLeft="12"/> <Insets topRightBottomLeft="12"/>
</padding> </padding>
@@ -17,7 +17,8 @@
minWidth="400" minWidth="400"
maxWidth="400" maxWidth="400"
minHeight="145" minHeight="145"
spacing="12"> spacing="12"
accessibleRole="DIALOG">
<padding> <padding>
<Insets topRightBottomLeft="12"/> <Insets topRightBottomLeft="12"/>
</padding> </padding>
@@ -17,7 +17,8 @@
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>
@@ -12,7 +12,8 @@
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>
@@ -10,28 +10,29 @@
fx:controller="org.cryptomator.ui.recoverykey.RecoveryKeyValidateController" fx:controller="org.cryptomator.ui.recoverykey.RecoveryKeyValidateController"
maxWidth="400" maxWidth="400"
minHeight="145" minHeight="145"
spacing="12"> spacing="12"
accessibleRole="DIALOG">
<children> <children>
<FormattedLabel format="%recoveryKey.recover.prompt" arg1="${controller.vault.displayName}" wrapText="true" labelFor="$textarea"/> <FormattedLabel format="%recoveryKey.recover.prompt" arg1="${controller.vault.displayName}" wrapText="true" labelFor="$textarea"/>
<TextArea wrapText="true" prefRowCount="4" fx:id="textarea" textFormatter="${controller.recoveryKeyTextFormatter}" onKeyPressed="#onKeyPressed"/> <TextArea wrapText="true" prefRowCount="4" fx:id="textarea" textFormatter="${controller.recoveryKeyTextFormatter}" onKeyPressed="#onKeyPressed"/>
<VBox> <VBox>
<Label text="Just some Filler" visible="false" managed="${textarea.text.empty}" graphicTextGap="6"> <Label text="%recoveryKey.recover.wrongKey" visible="false" managed="${textarea.text.empty}" graphicTextGap="6" wrapText="true" >
<graphic> <graphic>
<FontAwesome5IconView glyph="ANCHOR"/> <FontAwesome5IconView glyph="ANCHOR"/>
</graphic> </graphic>
</Label> </Label>
<Label text="%recoveryKey.recover.correctKey" graphicTextGap="6" visible="${(!textarea.text.empty) &amp;&amp; controller.recoveryKeyCorrect}" managed="${(!textarea.text.empty) &amp;&amp; controller.recoveryKeyCorrect}"> <Label text="%recoveryKey.recover.correctKey" graphicTextGap="6" wrapText="true" visible="${(!textarea.text.empty) &amp;&amp; controller.recoveryKeyCorrect}" managed="${(!textarea.text.empty) &amp;&amp; controller.recoveryKeyCorrect}">
<graphic> <graphic>
<FontAwesome5IconView glyph="CHECK"/> <FontAwesome5IconView glyph="CHECK"/>
</graphic> </graphic>
</Label> </Label>
<Label text="%recoveryKey.recover.wrongKey" graphicTextGap="6" visible="${(!textarea.text.empty) &amp;&amp; controller.recoveryKeyWrong}" managed="${(!textarea.text.empty) &amp;&amp; controller.recoveryKeyWrong}"> <Label text="%recoveryKey.recover.wrongKey" graphicTextGap="6" wrapText="true" visible="${(!textarea.text.empty) &amp;&amp; controller.recoveryKeyWrong}" managed="${(!textarea.text.empty) &amp;&amp; controller.recoveryKeyWrong}">
<graphic> <graphic>
<FontAwesome5IconView glyph="TIMES" styleClass="glyph-icon-red"/> <FontAwesome5IconView glyph="TIMES" styleClass="glyph-icon-red"/>
</graphic> </graphic>
</Label> </Label>
<Label text="%recoveryKey.recover.invalidKey" graphicTextGap="6" visible="${(!textarea.text.empty) &amp;&amp; controller.recoveryKeyInvalid}" managed="${(!textarea.text.empty) &amp;&amp; controller.recoveryKeyInvalid}"> <Label text="%recoveryKey.recover.invalidKey" graphicTextGap="6" wrapText="true" visible="${(!textarea.text.empty) &amp;&amp; controller.recoveryKeyInvalid}" managed="${(!textarea.text.empty) &amp;&amp; controller.recoveryKeyInvalid}">
<graphic> <graphic>
<FontAwesome5IconView glyph="TIMES" styleClass="glyph-icon-red"/> <FontAwesome5IconView glyph="TIMES" styleClass="glyph-icon-red"/>
</graphic> </graphic>
+2 -1
View File
@@ -21,7 +21,8 @@
xmlns="http://javafx.com/javafx" xmlns="http://javafx.com/javafx"
fx:controller="org.cryptomator.ui.sharevault.ShareVaultController" fx:controller="org.cryptomator.ui.sharevault.ShareVaultController"
prefWidth="540" prefWidth="540"
spacing="12"> spacing="12"
accessibleRole="DIALOG">
<padding> <padding>
<Insets topRightBottomLeft="12"/> <Insets topRightBottomLeft="12"/>
</padding> </padding>
+2 -1
View File
@@ -17,7 +17,8 @@
minWidth="400" minWidth="400"
maxWidth="400" maxWidth="400"
minHeight="145" minHeight="145"
spacing="12"> spacing="12"
accessibleRole="DIALOG">
<padding> <padding>
<Insets topRightBottomLeft="12"/> <Insets topRightBottomLeft="12"/>
</padding> </padding>
@@ -18,7 +18,8 @@
minWidth="400" minWidth="400"
maxWidth="400" maxWidth="400"
minHeight="145" minHeight="145"
spacing="12"> spacing="12"
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